2 * sre-save.c: Routine for saving an image to a file.
6 * Paolo Molaro (lupus@ximian.com)
8 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10 * Copyright 2011 Rodrigo Kumpera
11 * Copyright 2016 Microsoft
13 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
19 #include "mono/metadata/dynamic-image-internals.h"
20 #include "mono/metadata/dynamic-stream-internals.h"
21 #include "mono/metadata/mono-ptr-array.h"
22 #include "mono/metadata/object-internals.h"
23 #include "mono/metadata/sre-internals.h"
24 #include "mono/metadata/security-manager.h"
25 #include "mono/metadata/tabledefs.h"
26 #include "mono/metadata/tokentype.h"
28 #include "mono/utils/checked-build.h"
29 #include "mono/utils/mono-digest.h"
30 #include "mono/utils/mono-error-internals.h"
32 #define TEXT_OFFSET 512
33 #define CLI_H_SIZE 136
34 #define FILE_ALIGN 512
35 #define VIRT_ALIGN 8192
36 #define START_TEXT_RVA 0x00002000
38 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
41 alloc_table (MonoDynamicTable *table, guint nrows)
43 mono_dynimage_alloc_table (table, nrows);
47 string_heap_insert (MonoDynamicStream *sh, const char *str)
49 return mono_dynstream_insert_string (sh, str);
53 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str, MonoError *error)
55 return mono_dynstream_insert_mstring (sh, str, error);
59 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
61 return mono_dynstream_add_data (stream, data, len);
65 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
67 return mono_dynstream_add_zero (stream, len);
71 stream_data_align (MonoDynamicStream *stream)
73 mono_dynstream_data_align (stream);
77 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
79 return mono_dynimage_encode_typedef_or_ref_full (assembly, type, TRUE);
83 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
85 MONO_REQ_GC_NEUTRAL_MODE;
88 MonoDynamicTable *table;
91 table = &assembly->tables [table_idx];
93 g_assert (col < table->columns);
95 values = table->values + table->columns;
96 for (i = 1; i <= table->rows; ++i) {
97 if (values [col] == token)
99 values += table->columns;
105 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
106 * dest may be misaligned.
109 swap_with_size (char *dest, const char* val, int len, int nelem) {
110 MONO_REQ_GC_NEUTRAL_MODE;
111 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
114 for (elem = 0; elem < nelem; ++elem) {
140 g_assert_not_reached ();
146 memcpy (dest, val, len * nelem);
151 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
153 MONO_REQ_GC_UNSAFE_MODE;
157 guint32 idx = 0, len;
159 len = str->length * 2;
160 mono_metadata_encode_value (len, b, &b);
161 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
163 char *swapped = g_malloc (2 * mono_string_length (str));
164 const char *p = (const char*)mono_string_chars (str);
166 swap_with_size (swapped, p, 2, mono_string_length (str));
167 idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
171 idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
177 * idx is the table index of the object
178 * type is one of MONO_CUSTOM_ATTR_*
181 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
183 MONO_REQ_GC_UNSAFE_MODE;
185 MonoDynamicTable *table;
186 MonoReflectionCustomAttr *cattr;
188 guint32 count, i, token;
192 mono_error_init (error);
194 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
197 count = mono_array_length (cattrs);
198 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
199 table->rows += count;
200 alloc_table (table, table->rows);
201 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
202 idx <<= MONO_CUSTOM_ATTR_BITS;
204 for (i = 0; i < count; ++i) {
205 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
206 values [MONO_CUSTOM_ATTR_PARENT] = idx;
207 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
208 if (!mono_error_ok (error)) goto fail;
209 type = mono_metadata_token_index (token);
210 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
211 switch (mono_metadata_token_table (token)) {
212 case MONO_TABLE_METHOD:
213 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
215 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
216 * method, not the one returned by mono_image_create_token ().
218 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
220 case MONO_TABLE_MEMBERREF:
221 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
224 g_warning ("got wrong token in custom attr");
227 values [MONO_CUSTOM_ATTR_TYPE] = type;
229 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
230 values [MONO_CUSTOM_ATTR_VALUE] = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, p - blob_size,
231 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
232 values += MONO_CUSTOM_ATTR_SIZE;
243 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
245 MONO_REQ_GC_UNSAFE_MODE;
247 MonoDynamicTable *table;
249 guint32 count, i, idx;
250 MonoReflectionPermissionSet *perm;
255 count = mono_array_length (permissions);
256 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
257 table->rows += count;
258 alloc_table (table, table->rows);
260 for (i = 0; i < mono_array_length (permissions); ++i) {
261 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
263 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
265 idx = mono_metadata_token_index (parent_token);
266 idx <<= MONO_HAS_DECL_SECURITY_BITS;
267 switch (mono_metadata_token_table (parent_token)) {
268 case MONO_TABLE_TYPEDEF:
269 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
271 case MONO_TABLE_METHOD:
272 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
274 case MONO_TABLE_ASSEMBLY:
275 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
278 g_assert_not_reached ();
281 values [MONO_DECL_SECURITY_ACTION] = perm->action;
282 values [MONO_DECL_SECURITY_PARENT] = idx;
283 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
290 * method_encode_code:
292 * @assembly the assembly
293 * @mb the managed MethodBuilder
294 * @error set on error
296 * Note that the return value is not sensible if @error is set.
299 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
301 MONO_REQ_GC_UNSAFE_MODE;
307 gint32 num_locals = 0;
308 gint32 num_exception = 0;
311 char fat_header [12];
314 guint32 local_sig = 0;
315 guint32 header_size = 12;
318 mono_error_init (error);
320 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
321 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
325 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
327 code = mb->ilgen->code;
328 code_size = mb->ilgen->code_len;
329 max_stack = mb->ilgen->max_stack;
330 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
331 if (mb->ilgen->ex_handlers)
332 num_exception = mono_reflection_method_count_clauses (mb->ilgen);
336 MonoError inner_error;
337 char *name = mono_string_to_utf8_checked (mb->name, &inner_error);
338 if (!is_ok (&inner_error)) {
339 name = g_strdup ("");
340 mono_error_cleanup (&inner_error);
342 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
343 mono_error_set_argument (error, NULL, "a method does not have any IL associated");
349 code_size = mono_array_length (code);
350 max_stack = 8; /* we probably need to run a verifier on the code... */
353 stream_data_align (&assembly->code);
355 /* check for exceptions, maxstack, locals */
356 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
358 if (code_size < 64 && !(code_size & 1)) {
359 flags = (code_size << 2) | 0x2;
360 } else if (code_size < 32 && (code_size & 1)) {
361 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
365 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
366 /* add to the fixup todo list */
367 if (mb->ilgen && mb->ilgen->num_token_fixups)
368 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
369 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
370 return assembly->text_rva + idx;
374 local_sig = MONO_TOKEN_SIGNATURE | mono_dynimage_encode_locals (assembly, mb->ilgen, error);
375 return_val_if_nok (error, 0);
378 * FIXME: need to set also the header size in fat_flags.
379 * (and more sects and init locals flags)
383 fat_flags |= METHOD_HEADER_MORE_SECTS;
385 fat_flags |= METHOD_HEADER_INIT_LOCALS;
386 fat_header [0] = fat_flags;
387 fat_header [1] = (header_size / 4 ) << 4;
388 short_value = GUINT16_TO_LE (max_stack);
389 memcpy (fat_header + 2, &short_value, 2);
390 int_value = GUINT32_TO_LE (code_size);
391 memcpy (fat_header + 4, &int_value, 4);
392 int_value = GUINT32_TO_LE (local_sig);
393 memcpy (fat_header + 8, &int_value, 4);
394 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
395 /* add to the fixup todo list */
396 if (mb->ilgen && mb->ilgen->num_token_fixups)
397 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
399 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
401 unsigned char sheader [4];
402 MonoILExceptionInfo * ex_info;
403 MonoILExceptionBlock * ex_block;
406 stream_data_align (&assembly->code);
407 /* always use fat format for now */
408 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
409 num_exception *= 6 * sizeof (guint32);
410 num_exception += 4; /* include the size of the header */
411 sheader [1] = num_exception & 0xff;
412 sheader [2] = (num_exception >> 8) & 0xff;
413 sheader [3] = (num_exception >> 16) & 0xff;
414 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
415 /* fat header, so we are already aligned */
417 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
418 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
419 if (ex_info->handlers) {
420 int finally_start = ex_info->start + ex_info->len;
421 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
423 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
425 val = GUINT32_TO_LE (ex_block->type);
426 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
428 val = GUINT32_TO_LE (ex_info->start);
429 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
430 /* need fault, too, probably */
431 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
432 val = GUINT32_TO_LE (finally_start - ex_info->start);
434 val = GUINT32_TO_LE (ex_info->len);
435 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
437 val = GUINT32_TO_LE (ex_block->start);
438 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
440 val = GUINT32_TO_LE (ex_block->len);
441 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
442 finally_start = ex_block->start + ex_block->len;
443 if (ex_block->extype) {
444 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
445 return_val_if_nok (error, 0);
447 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
449 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
450 val = ex_block->filter_offset;
454 val = GUINT32_TO_LE (val);
455 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
456 /*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",
457 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);*/
460 g_error ("No clauses for ex info block %d", i);
464 return assembly->text_rva + idx;
468 * Fill in the MethodDef and ParamDef tables for a method.
469 * This is used for both normal methods and constructors.
472 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
474 MONO_REQ_GC_UNSAFE_MODE;
476 MonoDynamicTable *table;
480 mono_error_init (error);
482 /* room in this table is already allocated */
483 table = &assembly->tables [MONO_TABLE_METHOD];
484 *mb->table_idx = table->next_idx ++;
485 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
486 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
487 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
488 return_val_if_nok (error, FALSE);
489 values [MONO_METHOD_FLAGS] = mb->attrs;
490 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
491 values [MONO_METHOD_SIGNATURE] = mono_dynimage_encode_method_builder_signature (assembly, mb, error);
492 return_val_if_nok (error, FALSE);
493 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
494 return_val_if_nok (error, FALSE);
496 table = &assembly->tables [MONO_TABLE_PARAM];
497 values [MONO_METHOD_PARAMLIST] = table->next_idx;
499 mono_image_add_decl_security (assembly,
500 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
503 MonoDynamicTable *mtable;
506 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
507 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
510 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
511 if (mono_array_get (mb->pinfo, gpointer, i))
514 table->rows += count;
515 alloc_table (table, table->rows);
516 values = table->values + table->next_idx * MONO_PARAM_SIZE;
517 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
518 MonoReflectionParamBuilder *pb;
519 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
520 values [MONO_PARAM_FLAGS] = pb->attrs;
521 values [MONO_PARAM_SEQUENCE] = i;
522 if (pb->name != NULL) {
523 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
524 return_val_if_nok (error, FALSE);
526 values [MONO_PARAM_NAME] = 0;
528 values += MONO_PARAM_SIZE;
529 if (pb->marshal_info) {
531 alloc_table (mtable, mtable->rows);
532 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
533 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
534 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = mono_dynimage_save_encode_marshal_blob (assembly, pb->marshal_info, error);
535 return_val_if_nok (error, FALSE);
537 pb->table_idx = table->next_idx++;
538 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
539 guint32 field_type = 0;
540 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
542 alloc_table (mtable, mtable->rows);
543 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
544 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
545 mvalues [MONO_CONSTANT_VALUE] = mono_dynimage_encode_constant (assembly, pb->def_value, &field_type);
546 mvalues [MONO_CONSTANT_TYPE] = field_type;
547 mvalues [MONO_CONSTANT_PADDING] = 0;
557 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
559 MONO_REQ_GC_UNSAFE_MODE;
561 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
562 MonoDynamicTable *table;
565 MonoReflectionMethod *m;
568 mono_error_init (error);
570 if (!mb->override_methods)
573 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
574 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
576 table = &assembly->tables [MONO_TABLE_METHODIMPL];
578 alloc_table (table, table->rows);
579 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
580 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
581 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
583 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
584 return_val_if_nok (error, FALSE);
586 switch (mono_metadata_token_table (tok)) {
587 case MONO_TABLE_MEMBERREF:
588 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
590 case MONO_TABLE_METHOD:
591 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
594 g_assert_not_reached ();
596 values [MONO_METHODIMPL_DECLARATION] = tok;
602 #ifndef DISABLE_REFLECTION_EMIT
604 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
606 MONO_REQ_GC_UNSAFE_MODE;
608 MonoDynamicTable *table;
610 ReflectionMethodBuilder rmb;
613 mono_error_init (error);
615 if (!mono_reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
616 !mono_image_basic_method (&rmb, assembly, error))
619 mb->table_idx = *rmb.table_idx;
621 if (mb->dll) { /* It's a P/Invoke method */
623 /* map CharSet values to on-disk values */
624 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
625 int extra_flags = mb->extra_flags;
626 table = &assembly->tables [MONO_TABLE_IMPLMAP];
628 alloc_table (table, table->rows);
629 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
631 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
632 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
634 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry, error);
635 return_val_if_nok (error, FALSE);
637 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
638 return_val_if_nok (error, FALSE);
640 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll, error);
641 return_val_if_nok (error, FALSE);
642 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
643 table = &assembly->tables [MONO_TABLE_MODULEREF];
645 alloc_table (table, table->rows);
646 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
647 values [MONO_IMPLMAP_SCOPE] = table->rows;
651 if (mb->generic_params) {
652 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
653 table->rows += mono_array_length (mb->generic_params);
654 alloc_table (table, table->rows);
655 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
656 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
658 mono_image_get_generic_param_info (
659 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
667 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
669 MONO_REQ_GC_UNSAFE_MODE;
671 ReflectionMethodBuilder rmb;
673 if (!mono_reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
676 if (!mono_image_basic_method (&rmb, assembly, error))
679 mb->table_idx = *rmb.table_idx;
686 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
688 MONO_REQ_GC_UNSAFE_MODE;
690 mono_error_init (error);
692 MonoDynamicTable *table;
695 /* maybe this fixup should be done in the C# code */
696 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
697 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
698 table = &assembly->tables [MONO_TABLE_FIELD];
699 fb->table_idx = table->next_idx ++;
700 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
701 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
702 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name, error);
703 return_if_nok (error);
704 values [MONO_FIELD_FLAGS] = fb->attrs;
705 values [MONO_FIELD_SIGNATURE] = mono_dynimage_encode_field_signature (assembly, fb, error);
706 return_if_nok (error);
709 if (fb->offset != -1) {
710 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
712 alloc_table (table, table->rows);
713 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
714 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
715 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
717 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
718 MonoTypeEnum field_type = (MonoTypeEnum)0;
719 table = &assembly->tables [MONO_TABLE_CONSTANT];
721 alloc_table (table, table->rows);
722 values = table->values + table->rows * MONO_CONSTANT_SIZE;
723 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
724 values [MONO_CONSTANT_VALUE] = mono_dynimage_encode_constant (assembly, fb->def_value, &field_type);
725 values [MONO_CONSTANT_TYPE] = field_type;
726 values [MONO_CONSTANT_PADDING] = 0;
728 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
730 table = &assembly->tables [MONO_TABLE_FIELDRVA];
732 alloc_table (table, table->rows);
733 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
734 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
736 * We store it in the code section because it's simpler for now.
739 if (mono_array_length (fb->rva_data) >= 10)
740 stream_data_align (&assembly->code);
741 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
743 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
744 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
746 if (fb->marshal_info) {
747 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
749 alloc_table (table, table->rows);
750 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
751 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
752 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = mono_dynimage_save_encode_marshal_blob (assembly, fb->marshal_info, error);
753 return_if_nok (error);
758 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
760 MONO_REQ_GC_UNSAFE_MODE;
762 mono_error_init (error);
764 MonoDynamicTable *table;
766 guint num_methods = 0;
770 * we need to set things in the following tables:
771 * PROPERTYMAP (info already filled in _get_type_info ())
772 * PROPERTY (rows already preallocated in _get_type_info ())
773 * METHOD (method info already done with the generic method code)
777 table = &assembly->tables [MONO_TABLE_PROPERTY];
778 pb->table_idx = table->next_idx ++;
779 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
780 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
781 return_if_nok (error);
782 values [MONO_PROPERTY_FLAGS] = pb->attrs;
783 values [MONO_PROPERTY_TYPE] = mono_dynimage_save_encode_property_signature (assembly, pb, error);
784 return_if_nok (error);
787 /* FIXME: we still don't handle 'other' methods */
788 if (pb->get_method) num_methods ++;
789 if (pb->set_method) num_methods ++;
791 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
792 table->rows += num_methods;
793 alloc_table (table, table->rows);
795 if (pb->get_method) {
796 semaidx = table->next_idx ++;
797 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
798 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
799 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
800 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
802 if (pb->set_method) {
803 semaidx = table->next_idx ++;
804 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
805 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
806 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
807 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
809 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
810 MonoTypeEnum field_type = (MonoTypeEnum)0;
811 table = &assembly->tables [MONO_TABLE_CONSTANT];
813 alloc_table (table, table->rows);
814 values = table->values + table->rows * MONO_CONSTANT_SIZE;
815 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
816 values [MONO_CONSTANT_VALUE] = mono_dynimage_encode_constant (assembly, pb->def_value, &field_type);
817 values [MONO_CONSTANT_TYPE] = field_type;
818 values [MONO_CONSTANT_PADDING] = 0;
823 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
825 MONO_REQ_GC_UNSAFE_MODE;
827 MonoDynamicTable *table;
829 guint num_methods = 0;
833 * we need to set things in the following tables:
834 * EVENTMAP (info already filled in _get_type_info ())
835 * EVENT (rows already preallocated in _get_type_info ())
836 * METHOD (method info already done with the generic method code)
839 table = &assembly->tables [MONO_TABLE_EVENT];
840 eb->table_idx = table->next_idx ++;
841 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
842 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name, error);
843 return_if_nok (error);
844 values [MONO_EVENT_FLAGS] = eb->attrs;
845 MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
846 return_if_nok (error);
847 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
850 * FIXME: we still don't handle 'other' methods
852 if (eb->add_method) num_methods ++;
853 if (eb->remove_method) num_methods ++;
854 if (eb->raise_method) num_methods ++;
856 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
857 table->rows += num_methods;
858 alloc_table (table, table->rows);
860 if (eb->add_method) {
861 semaidx = table->next_idx ++;
862 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
863 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
864 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
865 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
867 if (eb->remove_method) {
868 semaidx = table->next_idx ++;
869 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
870 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
871 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
872 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
874 if (eb->raise_method) {
875 semaidx = table->next_idx ++;
876 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
877 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
878 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
879 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
884 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
886 MONO_REQ_GC_UNSAFE_MODE;
888 mono_error_init (error);
890 MonoDynamicTable *table;
891 guint32 num_constraints, i;
895 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
896 num_constraints = gparam->iface_constraints ?
897 mono_array_length (gparam->iface_constraints) : 0;
898 table->rows += num_constraints;
899 if (gparam->base_type)
901 alloc_table (table, table->rows);
903 if (gparam->base_type) {
904 table_idx = table->next_idx ++;
905 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
907 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
908 return_if_nok (error);
909 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
910 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
913 for (i = 0; i < num_constraints; i++) {
914 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
915 gparam->iface_constraints, gpointer, i);
917 table_idx = table->next_idx ++;
918 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
920 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
921 return_if_nok (error);
923 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
924 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
929 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
931 MONO_REQ_GC_UNSAFE_MODE;
933 GenericParamTableEntry *entry;
936 * The GenericParam table must be sorted according to the `owner' field.
937 * We need to do this sorting prior to writing the GenericParamConstraint
938 * table, since we have to use the final GenericParam table indices there
939 * and they must also be sorted.
942 entry = g_new0 (GenericParamTableEntry, 1);
943 entry->owner = owner;
944 /* FIXME: track where gen_params should be freed and remove the GC root as well */
945 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
946 entry->gparam = gparam;
948 g_ptr_array_add (assembly->gen_params, entry);
952 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
954 MONO_REQ_GC_UNSAFE_MODE;
956 MonoDynamicTable *table;
957 MonoGenericParam *param;
961 mono_error_init (error);
963 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
964 table_idx = table->next_idx ++;
965 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
967 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
968 return_val_if_nok (error, FALSE);
970 param = gparam_type->data.generic_param;
972 values [MONO_GENERICPARAM_OWNER] = entry->owner;
973 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
974 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
975 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
977 if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
980 encode_constraints (entry->gparam, table_idx, assembly, error);
981 return_val_if_nok (error, FALSE);
987 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
991 mono_ptr_array_append (*types, type);
996 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
997 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
998 collect_types (types, subtype);
1003 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
1005 if ((*type1)->table_idx < (*type2)->table_idx)
1008 if ((*type1)->table_idx > (*type2)->table_idx)
1015 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
1018 mono_error_init (error);
1021 for (i = 0; i < mono_array_length (pinfo); ++i) {
1022 MonoReflectionParamBuilder *pb;
1023 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
1026 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
1034 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
1037 mono_error_init (error);
1039 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
1042 for (i = 0; i < tb->num_fields; ++i) {
1043 MonoReflectionFieldBuilder* fb;
1044 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
1045 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
1050 for (i = 0; i < mono_array_length (tb->events); ++i) {
1051 MonoReflectionEventBuilder* eb;
1052 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
1053 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
1057 if (tb->properties) {
1058 for (i = 0; i < mono_array_length (tb->properties); ++i) {
1059 MonoReflectionPropertyBuilder* pb;
1060 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
1061 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
1066 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
1067 MonoReflectionCtorBuilder* cb;
1068 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
1069 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
1070 !params_add_cattrs (assembly, cb->pinfo, error))
1076 for (i = 0; i < tb->num_methods; ++i) {
1077 MonoReflectionMethodBuilder* mb;
1078 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
1079 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
1080 !params_add_cattrs (assembly, mb->pinfo, error))
1086 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1087 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
1096 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
1100 mono_error_init (error);
1102 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
1105 if (moduleb->global_methods) {
1106 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
1107 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
1108 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
1109 !params_add_cattrs (assembly, mb->pinfo, error))
1114 if (moduleb->global_fields) {
1115 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
1116 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
1117 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
1122 if (moduleb->types) {
1123 for (i = 0; i < moduleb->num_types; ++i) {
1124 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
1133 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly, MonoError *error)
1135 MonoDynamicTable *table;
1139 char *b = blob_size;
1142 mono_error_init (error);
1144 table = &assembly->tables [MONO_TABLE_FILE];
1146 alloc_table (table, table->rows);
1147 values = table->values + table->next_idx * MONO_FILE_SIZE;
1148 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
1149 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
1150 if (image_is_dynamic (module->image)) {
1151 /* This depends on the fact that the main module is emitted last */
1152 dir = mono_string_to_utf8_checked (((MonoReflectionModuleBuilder*)module)->assemblyb->dir, error);
1153 return_val_if_nok (error, FALSE);
1154 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
1157 path = g_strdup (module->image->name);
1159 mono_sha1_get_digest_from_file (path, hash);
1162 mono_metadata_encode_value (20, b, &b);
1163 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1164 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
1170 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1172 MonoDynamicTable *table;
1175 mono_error_init (error);
1177 table = &assembly->tables [MONO_TABLE_MODULE];
1178 mb->table_idx = table->next_idx ++;
1179 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name, error);
1180 return_if_nok (error);
1181 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
1184 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
1185 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
1186 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
1187 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
1191 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
1192 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
1194 MonoDynamicTable *table;
1198 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1199 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
1202 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
1204 alloc_table (table, table->rows);
1205 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
1207 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
1208 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
1209 if (klass->nested_in)
1210 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
1212 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
1213 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1214 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1216 res = table->next_idx;
1220 /* Emit nested types */
1221 if (klass->ext && klass->ext->nested_classes) {
1224 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
1225 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
1232 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
1233 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
1239 mono_error_init (error);
1241 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
1242 return_if_nok (error);
1244 klass = mono_class_from_mono_type (t);
1246 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
1248 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
1249 parent_index, assembly);
1253 * We need to do this ourselves since klass->nested_classes is not set up.
1256 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1257 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
1258 return_if_nok (error);
1264 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
1265 guint32 module_index, MonoDynamicImage *assembly)
1267 MonoImage *image = module->image;
1271 t = &image->tables [MONO_TABLE_TYPEDEF];
1273 for (i = 0; i < t->rows; ++i) {
1275 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
1276 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1278 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
1279 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
1284 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
1286 MonoDynamicTable *table;
1288 guint32 scope, scope_idx, impl, current_idx;
1289 gboolean forwarder = TRUE;
1290 gpointer iter = NULL;
1293 if (klass->nested_in) {
1294 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
1297 scope = mono_reflection_resolution_scope_from_image (assembly, klass->image);
1298 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
1299 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
1300 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
1303 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
1306 alloc_table (table, table->rows);
1307 current_idx = table->next_idx;
1308 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
1310 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
1311 values [MONO_EXP_TYPE_TYPEDEF] = 0;
1312 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
1313 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1314 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1318 while ((nested = mono_class_get_nested_types (klass, &iter)))
1319 add_exported_type (assemblyb, assembly, nested, current_idx);
1323 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
1329 if (!assemblyb->type_forwarders)
1332 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
1333 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
1338 type = mono_reflection_type_get_handle (t, &error);
1339 mono_error_assert_ok (&error);
1342 klass = mono_class_from_mono_type (type);
1344 add_exported_type (assemblyb, assembly, klass, 0);
1348 #define align_pointer(base,p)\
1350 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1352 (p) += 4 - (__diff & 3);\
1356 compare_constants (const void *a, const void *b)
1358 const guint32 *a_values = (const guint32 *)a;
1359 const guint32 *b_values = (const guint32 *)b;
1360 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
1364 compare_semantics (const void *a, const void *b)
1366 const guint32 *a_values = (const guint32 *)a;
1367 const guint32 *b_values = (const guint32 *)b;
1368 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
1371 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
1375 compare_custom_attrs (const void *a, const void *b)
1377 const guint32 *a_values = (const guint32 *)a;
1378 const guint32 *b_values = (const guint32 *)b;
1380 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
1384 compare_field_marshal (const void *a, const void *b)
1386 const guint32 *a_values = (const guint32 *)a;
1387 const guint32 *b_values = (const guint32 *)b;
1389 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
1393 compare_nested (const void *a, const void *b)
1395 const guint32 *a_values = (const guint32 *)a;
1396 const guint32 *b_values = (const guint32 *)b;
1398 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
1402 compare_genericparam (const void *a, const void *b)
1405 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
1406 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
1408 if ((*b_entry)->owner == (*a_entry)->owner) {
1409 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
1410 mono_error_assert_ok (&error);
1411 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
1412 mono_error_assert_ok (&error);
1414 mono_type_get_generic_param_num (a_type) -
1415 mono_type_get_generic_param_num (b_type);
1417 return (*a_entry)->owner - (*b_entry)->owner;
1421 compare_declsecurity_attrs (const void *a, const void *b)
1423 const guint32 *a_values = (const guint32 *)a;
1424 const guint32 *b_values = (const guint32 *)b;
1426 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
1430 compare_interface_impl (const void *a, const void *b)
1432 const guint32 *a_values = (const guint32 *)a;
1433 const guint32 *b_values = (const guint32 *)b;
1435 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
1439 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
1444 MonoDynamicStream *stream;
1448 * build_compressed_metadata() fills in the blob of data that represents the
1449 * raw metadata as it will be saved in the PE file. The five streams are output
1450 * and the metadata tables are comnpressed from the guint32 array representation,
1451 * to the compressed on-disk format.
1454 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
1456 MonoDynamicTable *table;
1458 guint64 valid_mask = 0;
1459 guint64 sorted_mask;
1460 guint32 heapt_size = 0;
1461 guint32 meta_size = 256; /* allow for header and other stuff */
1462 guint32 table_offset;
1463 guint32 ntables = 0;
1469 struct StreamDesc stream_desc [5];
1471 mono_error_init (error);
1473 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
1474 for (i = 0; i < assembly->gen_params->len; i++) {
1475 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
1476 if (!write_generic_param_entry (assembly, entry, error))
1480 stream_desc [0].name = "#~";
1481 stream_desc [0].stream = &assembly->tstream;
1482 stream_desc [1].name = "#Strings";
1483 stream_desc [1].stream = &assembly->sheap;
1484 stream_desc [2].name = "#US";
1485 stream_desc [2].stream = &assembly->us;
1486 stream_desc [3].name = "#Blob";
1487 stream_desc [3].stream = &assembly->blob;
1488 stream_desc [4].name = "#GUID";
1489 stream_desc [4].stream = &assembly->guid;
1491 /* tables that are sorted */
1492 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
1493 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
1494 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
1495 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
1496 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
1497 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
1498 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
1500 /* Compute table sizes */
1501 /* the MonoImage has already been created in mono_reflection_dynimage_basic_init() */
1502 meta = &assembly->image;
1504 /* sizes should be multiple of 4 */
1505 mono_dynstream_data_align (&assembly->blob);
1506 mono_dynstream_data_align (&assembly->guid);
1507 mono_dynstream_data_align (&assembly->sheap);
1508 mono_dynstream_data_align (&assembly->us);
1510 /* Setup the info used by compute_sizes () */
1511 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
1512 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
1513 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
1515 meta_size += assembly->blob.index;
1516 meta_size += assembly->guid.index;
1517 meta_size += assembly->sheap.index;
1518 meta_size += assembly->us.index;
1520 for (i=0; i < MONO_TABLE_NUM; ++i)
1521 meta->tables [i].rows = assembly->tables [i].rows;
1523 for (i = 0; i < MONO_TABLE_NUM; i++){
1524 if (meta->tables [i].rows == 0)
1526 valid_mask |= (guint64)1 << i;
1528 meta->tables [i].row_size = mono_metadata_compute_size (
1529 meta, i, &meta->tables [i].size_bitfield);
1530 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
1532 heapt_size += 24; /* #~ header size */
1533 heapt_size += ntables * 4;
1534 /* make multiple of 4 */
1537 meta_size += heapt_size;
1538 meta->raw_metadata = (char *)g_malloc0 (meta_size);
1539 p = (unsigned char*)meta->raw_metadata;
1540 /* the metadata signature */
1541 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
1542 /* version numbers and 4 bytes reserved */
1543 int16val = (guint16*)p;
1544 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
1545 *int16val = GUINT16_TO_LE (meta->md_version_minor);
1547 /* version string */
1548 int32val = (guint32*)p;
1549 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
1551 memcpy (p, meta->version, strlen (meta->version));
1552 p += GUINT32_FROM_LE (*int32val);
1553 align_pointer (meta->raw_metadata, p);
1554 int16val = (guint16*)p;
1555 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
1556 *int16val = GUINT16_TO_LE (5); /* number of streams */
1560 * write the stream info.
1562 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
1563 table_offset += 3; table_offset &= ~3;
1565 assembly->tstream.index = heapt_size;
1566 for (i = 0; i < 5; ++i) {
1567 int32val = (guint32*)p;
1568 stream_desc [i].stream->offset = table_offset;
1569 *int32val++ = GUINT32_TO_LE (table_offset);
1570 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
1571 table_offset += GUINT32_FROM_LE (*int32val);
1572 table_offset += 3; table_offset &= ~3;
1574 strcpy ((char*)p, stream_desc [i].name);
1575 p += strlen (stream_desc [i].name) + 1;
1576 align_pointer (meta->raw_metadata, p);
1579 * now copy the data, the table stream header and contents goes first.
1581 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
1582 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
1583 int32val = (guint32*)p;
1584 *int32val = GUINT32_TO_LE (0); /* reserved */
1587 *p++ = 2; /* version */
1590 if (meta->idx_string_wide)
1592 if (meta->idx_guid_wide)
1594 if (meta->idx_blob_wide)
1597 *p++ = 1; /* reserved */
1598 int64val = (guint64*)p;
1599 *int64val++ = GUINT64_TO_LE (valid_mask);
1600 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
1602 int32val = (guint32*)p;
1603 for (i = 0; i < MONO_TABLE_NUM; i++){
1604 if (meta->tables [i].rows == 0)
1606 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
1608 p = (unsigned char*)int32val;
1610 /* sort the tables that still need sorting */
1611 table = &assembly->tables [MONO_TABLE_CONSTANT];
1613 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
1614 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1616 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
1617 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1619 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
1620 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1622 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
1623 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1625 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
1626 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
1627 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1629 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
1630 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1632 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
1634 /* compress the tables */
1635 for (i = 0; i < MONO_TABLE_NUM; i++){
1638 guint32 bitfield = meta->tables [i].size_bitfield;
1639 if (!meta->tables [i].rows)
1641 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
1642 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
1643 meta->tables [i].base = (char*)p;
1644 for (row = 1; row <= meta->tables [i].rows; ++row) {
1645 values = assembly->tables [i].values + row * assembly->tables [i].columns;
1646 for (col = 0; col < assembly->tables [i].columns; ++col) {
1647 switch (mono_metadata_table_size (bitfield, col)) {
1649 *p++ = values [col];
1652 *p++ = values [col] & 0xff;
1653 *p++ = (values [col] >> 8) & 0xff;
1656 *p++ = values [col] & 0xff;
1657 *p++ = (values [col] >> 8) & 0xff;
1658 *p++ = (values [col] >> 16) & 0xff;
1659 *p++ = (values [col] >> 24) & 0xff;
1662 g_assert_not_reached ();
1666 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
1669 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
1670 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
1671 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
1672 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
1673 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
1675 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
1681 * Some tables in metadata need to be sorted according to some criteria, but
1682 * when methods and fields are first created with reflection, they may be assigned a token
1683 * that doesn't correspond to the final token they will get assigned after the sorting.
1684 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
1685 * with the reflection objects that represent them. Once all the tables are set up, the
1686 * reflection objects will contains the correct table index. fixup_method() will fixup the
1687 * tokens for the method with ILGenerator @ilgen.
1690 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
1692 guint32 code_idx = GPOINTER_TO_UINT (value);
1693 MonoReflectionILTokenInfo *iltoken;
1694 MonoReflectionFieldBuilder *field;
1695 MonoReflectionCtorBuilder *ctor;
1696 MonoReflectionMethodBuilder *method;
1697 MonoReflectionTypeBuilder *tb;
1698 MonoReflectionArrayMethod *am;
1700 unsigned char *target;
1702 for (i = 0; i < ilgen->num_token_fixups; ++i) {
1703 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
1704 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
1705 switch (target [3]) {
1706 case MONO_TABLE_FIELD:
1707 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
1708 field = (MonoReflectionFieldBuilder *)iltoken->member;
1709 idx = field->table_idx;
1710 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
1711 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
1712 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
1714 g_assert_not_reached ();
1717 case MONO_TABLE_METHOD:
1718 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
1719 method = (MonoReflectionMethodBuilder *)iltoken->member;
1720 idx = method->table_idx;
1721 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
1722 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
1723 idx = ctor->table_idx;
1724 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
1725 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
1726 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
1727 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
1729 g_assert_not_reached ();
1732 case MONO_TABLE_TYPEDEF:
1733 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
1734 g_assert_not_reached ();
1735 tb = (MonoReflectionTypeBuilder *)iltoken->member;
1736 idx = tb->table_idx;
1738 case MONO_TABLE_MEMBERREF:
1739 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
1740 am = (MonoReflectionArrayMethod*)iltoken->member;
1741 idx = am->table_idx;
1742 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
1743 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
1744 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
1745 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
1746 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
1747 g_assert (m->klass->generic_class || m->klass->generic_container);
1749 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
1751 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
1752 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
1753 g_assert (mono_is_sr_field_on_inst (f));
1755 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
1756 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
1758 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
1760 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
1762 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
1765 g_assert_not_reached ();
1768 case MONO_TABLE_METHODSPEC:
1769 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
1770 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
1771 g_assert (mono_method_signature (m)->generic_param_count);
1773 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
1775 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
1778 g_assert_not_reached ();
1782 g_error ("got unexpected table 0x%02x in fixup", target [3]);
1784 target [0] = idx & 0xff;
1785 target [1] = (idx >> 8) & 0xff;
1786 target [2] = (idx >> 16) & 0xff;
1793 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
1794 * value is not known when the table is emitted.
1797 fixup_cattrs (MonoDynamicImage *assembly)
1799 MonoDynamicTable *table;
1801 guint32 type, i, idx, token;
1804 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1806 for (i = 0; i < table->rows; ++i) {
1807 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
1809 type = values [MONO_CUSTOM_ATTR_TYPE];
1810 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
1811 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
1812 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
1813 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
1816 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
1817 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
1818 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
1819 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1820 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
1821 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
1822 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
1823 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1830 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation, MonoError *error)
1832 MonoDynamicTable *table;
1835 mono_error_init (error);
1837 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
1839 alloc_table (table, table->rows);
1840 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
1841 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
1842 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
1843 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name, error);
1844 return_val_if_nok (error, FALSE);
1845 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
1851 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, MonoError *error)
1853 MonoDynamicTable *table;
1857 char *b = blob_size;
1859 guint32 idx, offset;
1861 mono_error_init (error);
1863 if (rsrc->filename) {
1864 name = mono_string_to_utf8_checked (rsrc->filename, error);
1865 return_val_if_nok (error, FALSE);
1866 sname = g_path_get_basename (name);
1868 table = &assembly->tables [MONO_TABLE_FILE];
1870 alloc_table (table, table->rows);
1871 values = table->values + table->next_idx * MONO_FILE_SIZE;
1872 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
1873 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
1876 mono_sha1_get_digest_from_file (name, hash);
1877 mono_metadata_encode_value (20, b, &b);
1878 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1879 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
1881 idx = table->next_idx++;
1883 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
1889 data = mono_array_addr (rsrc->data, char, 0);
1890 len = mono_array_length (rsrc->data);
1896 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
1897 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
1898 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
1899 mono_image_add_stream_data (&assembly->resources, data, len);
1903 * The entry should be emitted into the MANIFESTRESOURCE table of
1904 * the main module, but that needs to reference the FILE table
1905 * which isn't emitted yet.
1912 return assembly_add_resource_manifest (mb, assembly, rsrc, idx, error);
1916 set_version_from_string (MonoString *version, guint32 *values, MonoError *error)
1918 gchar *ver, *p, *str;
1921 mono_error_init (error);
1923 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
1924 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
1925 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
1926 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
1929 ver = str = mono_string_to_utf8_checked (version, error);
1930 return_val_if_nok (error, FALSE);
1931 for (i = 0; i < 4; ++i) {
1932 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
1938 /* handle Revision and Build */
1949 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
1953 char *b = blob_size;
1958 len = mono_array_length (pkey);
1959 mono_metadata_encode_value (len, b, &b);
1960 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
1961 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
1963 assembly->public_key = (guint8 *)g_malloc (len);
1964 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
1965 assembly->public_key_len = len;
1967 /* Special case: check for ECMA key (16 bytes) */
1968 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
1969 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
1970 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
1971 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
1972 /* minimum key size (in 2.0) is 384 bits */
1973 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
1975 /* FIXME - verifier */
1976 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
1977 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
1979 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
1985 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
1987 MonoDynamicTable *table;
1988 MonoDynamicImage *assembly;
1989 MonoReflectionAssemblyBuilder *assemblyb;
1993 guint32 module_index;
1995 mono_error_init (error);
1997 assemblyb = moduleb->assemblyb;
1998 assembly = moduleb->dynamic_image;
1999 domain = mono_object_domain (assemblyb);
2001 /* Emit ASSEMBLY table */
2002 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
2003 alloc_table (table, 1);
2004 values = table->values + MONO_ASSEMBLY_SIZE;
2005 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
2006 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name, error);
2007 return_val_if_nok (error, FALSE);
2008 if (assemblyb->culture) {
2009 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture, error);
2010 return_val_if_nok (error, FALSE);
2012 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
2014 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
2015 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
2016 if (!set_version_from_string (assemblyb->version, values, error))
2019 /* Emit FILE + EXPORTED_TYPE table */
2021 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
2023 MonoReflectionModuleBuilder *file_module =
2024 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
2025 if (file_module != moduleb) {
2026 if (!mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly, error))
2029 if (file_module->types) {
2030 for (j = 0; j < file_module->num_types; ++j) {
2031 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
2032 mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
2033 return_val_if_nok (error, FALSE);
2038 if (assemblyb->loaded_modules) {
2039 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
2040 MonoReflectionModule *file_module =
2041 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
2042 if (!mono_image_fill_file_table (domain, file_module, assembly, error))
2045 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
2048 if (assemblyb->type_forwarders)
2049 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
2051 /* Emit MANIFESTRESOURCE table */
2053 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
2055 MonoReflectionModuleBuilder *file_module =
2056 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
2057 /* The table for the main module is emitted later */
2058 if (file_module != moduleb) {
2060 if (file_module->resources) {
2061 int len = mono_array_length (file_module->resources);
2062 for (j = 0; j < len; ++j) {
2063 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
2064 if (!assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS), error))
2073 #ifndef DISABLE_REFLECTION_EMIT_SAVE
2076 * Insert into the metadata tables all the info about the TypeBuilder tb.
2077 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2080 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
2082 MonoDynamicTable *table;
2084 int i, is_object = 0, is_system = 0;
2087 mono_error_init (error);
2089 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2090 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2091 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2092 n = mono_string_to_utf8_checked (tb->name, error);
2093 return_val_if_nok (error, FALSE);
2094 if (strcmp (n, "Object") == 0)
2096 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2098 n = mono_string_to_utf8_checked (tb->nspace, error);
2099 return_val_if_nok (error, FALSE);
2100 if (strcmp (n, "System") == 0)
2102 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2104 if (tb->parent && !(is_system && is_object) &&
2105 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2106 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
2107 return_val_if_nok (error, FALSE);
2108 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
2110 values [MONO_TYPEDEF_EXTENDS] = 0;
2112 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2113 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2116 * if we have explicitlayout or sequentiallayouts, output data in the
2117 * ClassLayout table.
2119 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2120 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2121 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2123 alloc_table (table, table->rows);
2124 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2125 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2126 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2127 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2130 /* handle interfaces */
2131 if (tb->interfaces) {
2132 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2134 table->rows += mono_array_length (tb->interfaces);
2135 alloc_table (table, table->rows);
2136 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2137 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2138 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2139 MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
2140 return_val_if_nok (error, FALSE);
2141 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2142 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
2143 values += MONO_INTERFACEIMPL_SIZE;
2149 table = &assembly->tables [MONO_TABLE_FIELD];
2150 table->rows += tb->num_fields;
2151 alloc_table (table, table->rows);
2152 for (i = 0; i < tb->num_fields; ++i) {
2153 mono_image_get_field_info (
2154 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
2155 return_val_if_nok (error, FALSE);
2159 /* handle constructors */
2161 table = &assembly->tables [MONO_TABLE_METHOD];
2162 table->rows += mono_array_length (tb->ctors);
2163 alloc_table (table, table->rows);
2164 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2165 if (!mono_image_get_ctor_info (domain,
2166 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
2172 /* handle methods */
2174 table = &assembly->tables [MONO_TABLE_METHOD];
2175 table->rows += tb->num_methods;
2176 alloc_table (table, table->rows);
2177 for (i = 0; i < tb->num_methods; ++i) {
2178 if (!mono_image_get_method_info (
2179 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
2184 /* Do the same with properties etc.. */
2185 if (tb->events && mono_array_length (tb->events)) {
2186 table = &assembly->tables [MONO_TABLE_EVENT];
2187 table->rows += mono_array_length (tb->events);
2188 alloc_table (table, table->rows);
2189 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2191 alloc_table (table, table->rows);
2192 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2193 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2194 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2195 for (i = 0; i < mono_array_length (tb->events); ++i) {
2196 mono_image_get_event_info (
2197 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
2198 return_val_if_nok (error, FALSE);
2201 if (tb->properties && mono_array_length (tb->properties)) {
2202 table = &assembly->tables [MONO_TABLE_PROPERTY];
2203 table->rows += mono_array_length (tb->properties);
2204 alloc_table (table, table->rows);
2205 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2207 alloc_table (table, table->rows);
2208 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2209 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2210 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2211 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2212 mono_image_get_property_info (
2213 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
2214 return_val_if_nok (error, FALSE);
2218 /* handle generic parameters */
2219 if (tb->generic_params) {
2220 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2221 table->rows += mono_array_length (tb->generic_params);
2222 alloc_table (table, table->rows);
2223 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2224 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2226 mono_image_get_generic_param_info (
2227 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2231 mono_image_add_decl_security (assembly,
2232 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2235 MonoDynamicTable *ntable;
2237 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2238 ntable->rows += mono_array_length (tb->subtypes);
2239 alloc_table (ntable, ntable->rows);
2240 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2242 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2243 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2245 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2246 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2247 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2248 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2249 mono_string_to_utf8 (tb->name), tb->table_idx,
2250 ntable->next_idx, ntable->rows);*/
2251 values += MONO_NESTED_CLASS_SIZE;
2261 * mono_image_build_metadata() will fill the info in all the needed metadata tables
2262 * for the modulebuilder @moduleb.
2263 * At the end of the process, method and field tokens are fixed up and the
2264 * on-disk compressed metadata representation is created.
2265 * Return TRUE on success, or FALSE on failure and sets @error
2268 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
2270 MonoDynamicTable *table;
2271 MonoDynamicImage *assembly;
2272 MonoReflectionAssemblyBuilder *assemblyb;
2278 mono_error_init (error);
2280 assemblyb = moduleb->assemblyb;
2281 assembly = moduleb->dynamic_image;
2282 domain = mono_object_domain (assemblyb);
2284 if (assembly->text_rva)
2287 assembly->text_rva = START_TEXT_RVA;
2289 if (moduleb->is_main) {
2290 mono_image_emit_manifest (moduleb, error);
2291 return_val_if_nok (error, FALSE);
2294 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2295 table->rows = 1; /* .<Module> */
2297 alloc_table (table, table->rows);
2299 * Set the first entry.
2301 values = table->values + table->columns;
2302 values [MONO_TYPEDEF_FLAGS] = 0;
2303 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
2304 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
2305 values [MONO_TYPEDEF_EXTENDS] = 0;
2306 values [MONO_TYPEDEF_FIELD_LIST] = 1;
2307 values [MONO_TYPEDEF_METHOD_LIST] = 1;
2310 * handle global methods
2311 * FIXME: test what to do when global methods are defined in multiple modules.
2313 if (moduleb->global_methods) {
2314 table = &assembly->tables [MONO_TABLE_METHOD];
2315 table->rows += mono_array_length (moduleb->global_methods);
2316 alloc_table (table, table->rows);
2317 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
2318 if (!mono_image_get_method_info (
2319 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
2323 if (moduleb->global_fields) {
2324 table = &assembly->tables [MONO_TABLE_FIELD];
2325 table->rows += mono_array_length (moduleb->global_fields);
2326 alloc_table (table, table->rows);
2327 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
2328 mono_image_get_field_info (
2329 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
2336 table = &assembly->tables [MONO_TABLE_MODULE];
2337 alloc_table (table, 1);
2338 mono_image_fill_module_table (domain, moduleb, assembly, error);
2342 /* Collect all types into a list sorted by their table_idx */
2343 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
2346 for (i = 0; i < moduleb->num_types; ++i) {
2347 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
2348 collect_types (&types, type);
2351 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
2352 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2353 table->rows += mono_ptr_array_size (types);
2354 alloc_table (table, table->rows);
2357 * Emit type names + namespaces at one place inside the string heap,
2358 * so load_class_names () needs to touch fewer pages.
2360 for (i = 0; i < mono_ptr_array_size (types); ++i) {
2361 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
2362 string_heap_insert_mstring (&assembly->sheap, tb->nspace, error);
2366 for (i = 0; i < mono_ptr_array_size (types); ++i) {
2367 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
2368 string_heap_insert_mstring (&assembly->sheap, tb->name, error);
2373 for (i = 0; i < mono_ptr_array_size (types); ++i) {
2374 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
2375 if (!mono_image_get_type_info (domain, type, assembly, error))
2380 * table->rows is already set above and in mono_image_fill_module_table.
2382 /* add all the custom attributes at the end, once all the indexes are stable */
2383 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
2386 /* CAS assembly permissions */
2387 if (assemblyb->permissions_minimum)
2388 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
2389 if (assemblyb->permissions_optional)
2390 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
2391 if (assemblyb->permissions_refused)
2392 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
2394 if (!module_add_cattrs (assembly, moduleb, error))
2398 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
2400 /* Create the MethodImpl table. We do this after emitting all methods so we already know
2401 * the final tokens and don't need another fixup pass. */
2403 if (moduleb->global_methods) {
2404 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
2405 MonoReflectionMethodBuilder *mb = mono_array_get (
2406 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
2407 if (!mono_image_add_methodimpl (assembly, mb, error))
2412 for (i = 0; i < mono_ptr_array_size (types); ++i) {
2413 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
2414 if (type->methods) {
2415 for (j = 0; j < type->num_methods; ++j) {
2416 MonoReflectionMethodBuilder *mb = mono_array_get (
2417 type->methods, MonoReflectionMethodBuilder*, j);
2419 if (!mono_image_add_methodimpl (assembly, mb, error))
2425 fixup_cattrs (assembly);
2428 mono_ptr_array_destroy (types);
2431 return mono_error_ok (error);
2434 #else /* DISABLE_REFLECTION_EMIT_SAVE */
2437 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
2439 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
2442 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
2444 #ifndef DISABLE_REFLECTION_EMIT_SAVE
2447 calc_section_size (MonoDynamicImage *assembly)
2451 /* alignment constraints */
2452 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
2453 g_assert ((assembly->code.index % 4) == 0);
2454 assembly->meta_size += 3;
2455 assembly->meta_size &= ~3;
2456 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
2457 g_assert ((assembly->resources.index % 4) == 0);
2459 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
2460 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
2463 if (assembly->win32_res) {
2464 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
2466 assembly->sections [MONO_SECTION_RSRC].size = res_size;
2467 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
2471 assembly->sections [MONO_SECTION_RELOC].size = 12;
2472 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
2482 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
2486 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
2488 ResTreeNode *t1 = (ResTreeNode*)a;
2489 ResTreeNode *t2 = (ResTreeNode*)b;
2491 return t1->id - t2->id;
2495 * resource_tree_create:
2497 * Organize the resources into a resource tree.
2499 static ResTreeNode *
2500 resource_tree_create (MonoArray *win32_resources)
2502 ResTreeNode *tree, *res_node, *type_node, *lang_node;
2506 tree = g_new0 (ResTreeNode, 1);
2508 for (i = 0; i < mono_array_length (win32_resources); ++i) {
2509 MonoReflectionWin32Resource *win32_res =
2510 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
2514 /* FIXME: BUG: this stores managed references in unmanaged memory */
2515 lang_node = g_new0 (ResTreeNode, 1);
2516 lang_node->id = win32_res->lang_id;
2517 lang_node->win32_res = win32_res;
2519 /* Create type node if neccesary */
2521 for (l = tree->children; l; l = l->next)
2522 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
2523 type_node = (ResTreeNode*)l->data;
2528 type_node = g_new0 (ResTreeNode, 1);
2529 type_node->id = win32_res->res_type;
2532 * The resource types have to be sorted otherwise
2533 * Windows Explorer can't display the version information.
2535 tree->children = g_slist_insert_sorted (tree->children,
2536 type_node, resource_tree_compare_by_id);
2539 /* Create res node if neccesary */
2541 for (l = type_node->children; l; l = l->next)
2542 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
2543 res_node = (ResTreeNode*)l->data;
2548 res_node = g_new0 (ResTreeNode, 1);
2549 res_node->id = win32_res->res_id;
2550 type_node->children = g_slist_append (type_node->children, res_node);
2553 res_node->children = g_slist_append (res_node->children, lang_node);
2560 * resource_tree_encode:
2562 * Encode the resource tree into the format used in the PE file.
2565 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
2568 MonoPEResourceDir dir;
2569 MonoPEResourceDirEntry dir_entry;
2570 MonoPEResourceDataEntry data_entry;
2572 guint32 res_id_entries;
2575 * For the format of the resource directory, see the article
2576 * "An In-Depth Look into the Win32 Portable Executable File Format" by
2580 memset (&dir, 0, sizeof (dir));
2581 memset (&dir_entry, 0, sizeof (dir_entry));
2582 memset (&data_entry, 0, sizeof (data_entry));
2584 g_assert (sizeof (dir) == 16);
2585 g_assert (sizeof (dir_entry) == 8);
2586 g_assert (sizeof (data_entry) == 16);
2588 node->offset = p - begin;
2590 /* IMAGE_RESOURCE_DIRECTORY */
2591 res_id_entries = g_slist_length (node->children);
2592 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
2594 memcpy (p, &dir, sizeof (dir));
2597 /* Reserve space for entries */
2599 p += sizeof (dir_entry) * res_id_entries;
2601 /* Write children */
2602 for (l = node->children; l; l = l->next) {
2603 ResTreeNode *child = (ResTreeNode*)l->data;
2605 if (child->win32_res) {
2608 child->offset = p - begin;
2610 /* IMAGE_RESOURCE_DATA_ENTRY */
2611 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
2612 size = mono_array_length (child->win32_res->res_data);
2613 data_entry.rde_size = GUINT32_TO_LE (size);
2615 memcpy (p, &data_entry, sizeof (data_entry));
2616 p += sizeof (data_entry);
2618 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
2621 resource_tree_encode (child, begin, p, &p);
2625 /* IMAGE_RESOURCE_ENTRY */
2626 for (l = node->children; l; l = l->next) {
2627 ResTreeNode *child = (ResTreeNode*)l->data;
2629 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
2630 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
2632 memcpy (entries, &dir_entry, sizeof (dir_entry));
2633 entries += sizeof (dir_entry);
2640 resource_tree_free (ResTreeNode * node)
2643 for (list = node->children; list; list = list->next)
2644 resource_tree_free ((ResTreeNode*)list->data);
2645 g_slist_free(node->children);
2650 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
2655 MonoReflectionWin32Resource *win32_res;
2658 if (!assemblyb->win32_resources)
2662 * Resources are stored in a three level tree inside the PE file.
2663 * - level one contains a node for each type of resource
2664 * - level two contains a node for each resource
2665 * - level three contains a node for each instance of a resource for a
2666 * specific language.
2669 tree = resource_tree_create (assemblyb->win32_resources);
2671 /* Estimate the size of the encoded tree */
2673 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
2674 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
2675 size += mono_array_length (win32_res->res_data);
2677 /* Directory structure */
2678 size += mono_array_length (assemblyb->win32_resources) * 256;
2679 p = buf = (char *)g_malloc (size);
2681 resource_tree_encode (tree, p, p, &p);
2683 g_assert (p - buf <= size);
2685 assembly->win32_res = (char *)g_malloc (p - buf);
2686 assembly->win32_res_size = p - buf;
2687 memcpy (assembly->win32_res, buf, p - buf);
2690 resource_tree_free (tree);
2694 fixup_resource_directory (char *res_section, char *p, guint32 rva)
2696 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
2699 p += sizeof (MonoPEResourceDir);
2700 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
2701 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
2702 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
2703 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
2704 fixup_resource_directory (res_section, child, rva);
2706 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
2707 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
2710 p += sizeof (MonoPEResourceDirEntry);
2715 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
2718 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
2719 g_error ("WriteFile returned %d\n", GetLastError ());
2723 * mono_image_create_pefile:
2724 * @mb: a module builder object
2726 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
2727 * assembly->pefile where it can be easily retrieved later in chunks.
2730 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
2732 MonoMSDOSHeader *msdos;
2733 MonoDotNetHeader *header;
2734 MonoSectionTable *section;
2735 MonoCLIHeader *cli_header;
2736 guint32 size, image_size, virtual_base, text_offset;
2737 guint32 header_start, section_start, file_offset, virtual_offset;
2738 MonoDynamicImage *assembly;
2739 MonoReflectionAssemblyBuilder *assemblyb;
2740 MonoDynamicStream pefile_stream = {0};
2741 MonoDynamicStream *pefile = &pefile_stream;
2743 guint32 *rva, value;
2745 static const unsigned char msheader[] = {
2746 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
2747 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2748 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2749 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
2750 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
2751 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
2752 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
2753 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2756 mono_error_init (error);
2758 assemblyb = mb->assemblyb;
2760 mono_reflection_dynimage_basic_init (assemblyb);
2761 assembly = mb->dynamic_image;
2763 assembly->pe_kind = assemblyb->pe_kind;
2764 assembly->machine = assemblyb->machine;
2765 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
2766 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
2768 if (!mono_image_build_metadata (mb, error))
2772 if (mb->is_main && assemblyb->resources) {
2773 int len = mono_array_length (assemblyb->resources);
2774 for (i = 0; i < len; ++i) {
2775 if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i), error))
2780 if (mb->resources) {
2781 int len = mono_array_length (mb->resources);
2782 for (i = 0; i < len; ++i) {
2783 if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i), error))
2788 if (!build_compressed_metadata (assembly, error))
2792 assembly_add_win32_resources (assembly, assemblyb);
2794 nsections = calc_section_size (assembly);
2796 /* The DOS header and stub */
2797 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
2798 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
2800 /* the dotnet header */
2801 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
2803 /* the section tables */
2804 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
2806 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
2807 virtual_offset = VIRT_ALIGN;
2810 for (i = 0; i < MONO_SECTION_MAX; ++i) {
2811 if (!assembly->sections [i].size)
2814 file_offset += FILE_ALIGN - 1;
2815 file_offset &= ~(FILE_ALIGN - 1);
2816 virtual_offset += VIRT_ALIGN - 1;
2817 virtual_offset &= ~(VIRT_ALIGN - 1);
2819 assembly->sections [i].offset = file_offset;
2820 assembly->sections [i].rva = virtual_offset;
2822 file_offset += assembly->sections [i].size;
2823 virtual_offset += assembly->sections [i].size;
2824 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
2827 file_offset += FILE_ALIGN - 1;
2828 file_offset &= ~(FILE_ALIGN - 1);
2830 image_size += section_start + sizeof (MonoSectionTable) * nsections;
2832 /* back-patch info */
2833 msdos = (MonoMSDOSHeader*)pefile->data;
2834 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
2836 header = (MonoDotNetHeader*)(pefile->data + header_start);
2837 header->pesig [0] = 'P';
2838 header->pesig [1] = 'E';
2840 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
2841 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
2842 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
2843 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
2844 if (assemblyb->pekind == 1) {
2846 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
2849 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
2852 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
2854 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
2855 header->pe.pe_major = 6;
2856 header->pe.pe_minor = 0;
2857 size = assembly->sections [MONO_SECTION_TEXT].size;
2858 size += FILE_ALIGN - 1;
2859 size &= ~(FILE_ALIGN - 1);
2860 header->pe.pe_code_size = GUINT32_FROM_LE(size);
2861 size = assembly->sections [MONO_SECTION_RSRC].size;
2862 size += FILE_ALIGN - 1;
2863 size &= ~(FILE_ALIGN - 1);
2864 header->pe.pe_data_size = GUINT32_FROM_LE(size);
2865 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
2866 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
2867 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2868 /* pe_rva_entry_point always at the beginning of the text section */
2869 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
2871 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
2872 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
2873 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
2874 header->nt.pe_os_major = GUINT16_FROM_LE (4);
2875 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
2876 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
2877 size = section_start;
2878 size += FILE_ALIGN - 1;
2879 size &= ~(FILE_ALIGN - 1);
2880 header->nt.pe_header_size = GUINT32_FROM_LE (size);
2882 size += VIRT_ALIGN - 1;
2883 size &= ~(VIRT_ALIGN - 1);
2884 header->nt.pe_image_size = GUINT32_FROM_LE (size);
2887 // Translate the PEFileKind value to the value expected by the Windows loader
2893 // PEFileKinds.Dll == 1
2894 // PEFileKinds.ConsoleApplication == 2
2895 // PEFileKinds.WindowApplication == 3
2898 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
2899 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
2901 if (assemblyb->pekind == 3)
2906 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
2908 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
2909 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
2910 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
2911 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
2912 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
2913 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
2915 /* fill data directory entries */
2917 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
2918 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2920 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
2921 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
2923 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
2924 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
2925 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
2926 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2927 /* patch entrypoint name */
2928 if (assemblyb->pekind == 1)
2929 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
2931 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
2932 /* patch imported function RVA name */
2933 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
2934 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
2936 /* the import table */
2937 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
2938 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
2939 /* patch imported dll RVA name and other entries in the dir */
2940 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
2941 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
2942 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
2943 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2944 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
2945 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
2947 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
2948 value = (assembly->text_rva + assembly->imp_names_offset);
2949 *p++ = (value) & 0xff;
2950 *p++ = (value >> 8) & (0xff);
2951 *p++ = (value >> 16) & (0xff);
2952 *p++ = (value >> 24) & (0xff);
2954 /* the CLI header info */
2955 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
2956 cli_header->ch_size = GUINT32_FROM_LE (72);
2957 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
2958 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
2959 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
2960 if (assemblyb->entry_point) {
2961 guint32 table_idx = 0;
2962 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
2963 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
2964 table_idx = methodb->table_idx;
2966 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
2968 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
2970 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
2972 /* The embedded managed resources */
2973 text_offset = assembly->text_rva + assembly->code.index;
2974 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
2975 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
2976 text_offset += assembly->resources.index;
2977 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
2978 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
2979 text_offset += assembly->meta_size;
2980 if (assembly->strong_name_size) {
2981 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
2982 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
2983 text_offset += assembly->strong_name_size;
2986 /* write the section tables and section content */
2987 section = (MonoSectionTable*)(pefile->data + section_start);
2988 for (i = 0; i < MONO_SECTION_MAX; ++i) {
2989 static const char section_names [][7] = {
2990 ".text", ".rsrc", ".reloc"
2992 if (!assembly->sections [i].size)
2994 strcpy (section->st_name, section_names [i]);
2995 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
2996 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
2997 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
2998 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
2999 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
3000 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
3001 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
3005 checked_write_file (file, pefile->data, pefile->index);
3007 mono_dynamic_stream_reset (pefile);
3009 for (i = 0; i < MONO_SECTION_MAX; ++i) {
3010 if (!assembly->sections [i].size)
3013 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
3014 g_error ("SetFilePointer returned %d\n", GetLastError ());
3017 case MONO_SECTION_TEXT:
3018 /* patch entry point */
3019 p = (guchar*)(assembly->code.data + 2);
3020 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
3021 *p++ = (value) & 0xff;
3022 *p++ = (value >> 8) & 0xff;
3023 *p++ = (value >> 16) & 0xff;
3024 *p++ = (value >> 24) & 0xff;
3026 checked_write_file (file, assembly->code.data, assembly->code.index);
3027 checked_write_file (file, assembly->resources.data, assembly->resources.index);
3028 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
3029 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
3032 g_free (assembly->image.raw_metadata);
3034 case MONO_SECTION_RELOC: {
3038 guint16 type_and_offset;
3042 g_assert (sizeof (reloc) == 12);
3044 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
3045 reloc.block_size = GUINT32_FROM_LE (12);
3048 * the entrypoint is always at the start of the text section
3049 * 3 is IMAGE_REL_BASED_HIGHLOW
3050 * 2 is patch_size_rva - text_rva
3052 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
3055 checked_write_file (file, &reloc, sizeof (reloc));
3059 case MONO_SECTION_RSRC:
3060 if (assembly->win32_res) {
3062 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
3063 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
3064 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
3068 g_assert_not_reached ();
3072 /* check that the file is properly padded */
3073 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
3074 g_error ("SetFilePointer returned %d\n", GetLastError ());
3075 if (! SetEndOfFile (file))
3076 g_error ("SetEndOfFile returned %d\n", GetLastError ());
3078 mono_dynamic_stream_reset (&assembly->code);
3079 mono_dynamic_stream_reset (&assembly->us);
3080 mono_dynamic_stream_reset (&assembly->blob);
3081 mono_dynamic_stream_reset (&assembly->guid);
3082 mono_dynamic_stream_reset (&assembly->sheap);
3084 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
3085 g_hash_table_destroy (assembly->blob_cache);
3086 assembly->blob_cache = NULL;
3091 #else /* DISABLE_REFLECTION_EMIT_SAVE */
3094 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
3096 g_assert_not_reached ();
3099 #endif /* DISABLE_REFLECTION_EMIT_SAVE */