[runtime] Move MonoClass::flags to MonoClassDef.
[mono.git] / mono / metadata / sre-save.c
1 /*
2  * sre-save.c: Routine for saving an image to a file.
3  *   
4  * 
5  * Author:
6  *   Paolo Molaro (lupus@ximian.com)
7  *
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
12  *
13  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
14  */
15
16 #include <config.h>
17 #include <glib.h>
18
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"
27
28 #include "mono/utils/checked-build.h"
29 #include "mono/utils/mono-digest.h"
30 #include "mono/utils/mono-error-internals.h"
31
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
37
38 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
39
40 static void
41 alloc_table (MonoDynamicTable *table, guint nrows)
42 {
43         mono_dynimage_alloc_table (table, nrows);
44 }
45
46 static guint32
47 string_heap_insert (MonoDynamicStream *sh, const char *str)
48 {
49         return mono_dynstream_insert_string (sh, str);
50 }
51
52 static guint32
53 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str, MonoError *error)
54 {
55         return mono_dynstream_insert_mstring (sh, str, error);
56 }
57
58 static guint32
59 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
60 {
61         return mono_dynstream_add_data (stream, data, len);
62 }
63
64 static guint32
65 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
66 {
67         return mono_dynstream_add_zero (stream, len);
68 }
69
70 static void
71 stream_data_align (MonoDynamicStream *stream)
72 {
73         mono_dynstream_data_align (stream);
74 }
75
76 static guint32
77 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
78 {
79         return mono_dynimage_encode_typedef_or_ref_full (assembly, type, TRUE);
80 }
81
82 static guint32
83 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
84 {
85         MONO_REQ_GC_NEUTRAL_MODE;
86
87         int i;
88         MonoDynamicTable *table;
89         guint32 *values;
90         
91         table = &assembly->tables [table_idx];
92
93         g_assert (col < table->columns);
94
95         values = table->values + table->columns;
96         for (i = 1; i <= table->rows; ++i) {
97                 if (values [col] == token)
98                         return i;
99                 values += table->columns;
100         }
101         return 0;
102 }
103
104 /*
105  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
106  * dest may be misaligned.
107  */
108 static void
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
112         int elem;
113
114         for (elem = 0; elem < nelem; ++elem) {
115                 switch (len) {
116                 case 1:
117                         *dest = *val;
118                         break;
119                 case 2:
120                         dest [0] = val [1];
121                         dest [1] = val [0];
122                         break;
123                 case 4:
124                         dest [0] = val [3];
125                         dest [1] = val [2];
126                         dest [2] = val [1];
127                         dest [3] = val [0];
128                         break;
129                 case 8:
130                         dest [0] = val [7];
131                         dest [1] = val [6];
132                         dest [2] = val [5];
133                         dest [3] = val [4];
134                         dest [4] = val [3];
135                         dest [5] = val [2];
136                         dest [6] = val [1];
137                         dest [7] = val [0];
138                         break;
139                 default:
140                         g_assert_not_reached ();
141                 }
142                 dest += len;
143                 val += len;
144         }
145 #else
146         memcpy (dest, val, len * nelem);
147 #endif
148 }
149
150 static guint32
151 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
152 {
153         MONO_REQ_GC_UNSAFE_MODE;
154         
155         char blob_size [64];
156         char *b = blob_size;
157         guint32 idx = 0, len;
158
159         len = str->length * 2;
160         mono_metadata_encode_value (len, b, &b);
161 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
162         {
163                 char *swapped = g_malloc (2 * mono_string_length (str));
164                 const char *p = (const char*)mono_string_chars (str);
165
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);
168                 g_free (swapped);
169         }
170 #else
171         idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
172 #endif
173         return idx;
174 }
175
176 /*
177  * idx is the table index of the object
178  * type is one of MONO_CUSTOM_ATTR_*
179  */
180 static gboolean
181 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
182 {
183         MONO_REQ_GC_UNSAFE_MODE;
184
185         MonoDynamicTable *table;
186         MonoReflectionCustomAttr *cattr;
187         guint32 *values;
188         guint32 count, i, token;
189         char blob_size [6];
190         char *p = blob_size;
191         
192         mono_error_init (error);
193
194         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
195         if (!cattrs)
196                 return TRUE;
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;
203         idx |= type;
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;
214                         /*
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 ().
217                          */
218                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
219                         break;
220                 case MONO_TABLE_MEMBERREF:
221                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
222                         break;
223                 default:
224                         g_warning ("got wrong token in custom attr");
225                         continue;
226                 }
227                 values [MONO_CUSTOM_ATTR_TYPE] = type;
228                 p = blob_size;
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;
233                 ++table->next_idx;
234         }
235
236         return TRUE;
237
238 fail:
239         return FALSE;
240 }
241
242 static void
243 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
244 {
245         MONO_REQ_GC_UNSAFE_MODE;
246
247         MonoDynamicTable *table;
248         guint32 *values;
249         guint32 count, i, idx;
250         MonoReflectionPermissionSet *perm;
251
252         if (!permissions)
253                 return;
254
255         count = mono_array_length (permissions);
256         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
257         table->rows += count;
258         alloc_table (table, table->rows);
259
260         for (i = 0; i < mono_array_length (permissions); ++i) {
261                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
262
263                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
264
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;
270                         break;
271                 case MONO_TABLE_METHOD:
272                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
273                         break;
274                 case MONO_TABLE_ASSEMBLY:
275                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
276                         break;
277                 default:
278                         g_assert_not_reached ();
279                 }
280
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);
284
285                 ++table->next_idx;
286         }
287 }
288
289 /**
290  * method_encode_code:
291  *
292  * @assembly the assembly
293  * @mb the managed MethodBuilder
294  * @error set on error
295  *
296  * Note that the return value is not sensible if @error is set.
297  */
298 static guint32
299 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
300 {
301         MONO_REQ_GC_UNSAFE_MODE;
302
303         char flags = 0;
304         guint32 idx;
305         guint32 code_size;
306         gint32 max_stack, i;
307         gint32 num_locals = 0;
308         gint32 num_exception = 0;
309         gint maybe_small;
310         guint32 fat_flags;
311         char fat_header [12];
312         guint32 int_value;
313         guint16 short_value;
314         guint32 local_sig = 0;
315         guint32 header_size = 12;
316         MonoArray *code;
317
318         mono_error_init (error);
319
320         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
321                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
322                 return 0;
323
324         /*if (mb->name)
325                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
326         if (mb->ilgen) {
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);
333         } else {
334                 code = mb->code;
335                 if (code == NULL){
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);
341                         }
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");
344                         g_free (str);
345                         g_free (name);
346                         return 0;
347                 }
348
349                 code_size = mono_array_length (code);
350                 max_stack = 8; /* we probably need to run a verifier on the code... */
351         }
352
353         stream_data_align (&assembly->code);
354
355         /* check for exceptions, maxstack, locals */
356         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
357         if (maybe_small) {
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 */
362                 } else {
363                         goto fat_header;
364                 }
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;
371         } 
372 fat_header:
373         if (num_locals) {
374                 local_sig = MONO_TOKEN_SIGNATURE | mono_dynimage_encode_locals (assembly, mb->ilgen, error);
375                 return_val_if_nok (error, 0);
376         }
377         /* 
378          * FIXME: need to set also the header size in fat_flags.
379          * (and more sects and init locals flags)
380          */
381         fat_flags =  0x03;
382         if (num_exception)
383                 fat_flags |= METHOD_HEADER_MORE_SECTS;
384         if (mb->init_locals)
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));
398         
399         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
400         if (num_exception) {
401                 unsigned char sheader [4];
402                 MonoILExceptionInfo * ex_info;
403                 MonoILExceptionBlock * ex_block;
404                 int j;
405
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 */
416                 /* reverse order */
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) {
422                                         guint32 val;
423                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
424                                         /* the flags */
425                                         val = GUINT32_TO_LE (ex_block->type);
426                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
427                                         /* try offset */
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);
433                                         else
434                                                 val = GUINT32_TO_LE (ex_info->len);
435                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
436                                         /* handler offset */
437                                         val = GUINT32_TO_LE (ex_block->start);
438                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
439                                         /* handler len */
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);
446
447                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
448                                         } else {
449                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
450                                                         val = ex_block->filter_offset;
451                                                 else
452                                                         val = 0;
453                                         }
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);*/
458                                 }
459                         } else {
460                                 g_error ("No clauses for ex info block %d", i);
461                         }
462                 }
463         }
464         return assembly->text_rva + idx;
465 }
466
467 /*
468  * Fill in the MethodDef and ParamDef tables for a method.
469  * This is used for both normal methods and constructors.
470  */
471 static gboolean
472 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
473 {
474         MONO_REQ_GC_UNSAFE_MODE;
475
476         MonoDynamicTable *table;
477         guint32 *values;
478         guint i, count;
479
480         mono_error_init (error);
481
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);
495
496         table = &assembly->tables [MONO_TABLE_PARAM];
497         values [MONO_METHOD_PARAMLIST] = table->next_idx;
498
499         mono_image_add_decl_security (assembly, 
500                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
501
502         if (mb->pinfo) {
503                 MonoDynamicTable *mtable;
504                 guint32 *mvalues;
505                 
506                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
507                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
508                 
509                 count = 0;
510                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
511                         if (mono_array_get (mb->pinfo, gpointer, i))
512                                 count++;
513                 }
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);
525                                 } else {
526                                         values [MONO_PARAM_NAME] = 0;
527                                 }
528                                 values += MONO_PARAM_SIZE;
529                                 if (pb->marshal_info) {
530                                         mtable->rows++;
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);
536                                 }
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];
541                                         mtable->rows ++;
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;
548                                 }
549                         }
550                 }
551         }
552
553         return TRUE;
554 }
555
556 static gboolean
557 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
558 {
559         MONO_REQ_GC_UNSAFE_MODE;
560
561         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
562         MonoDynamicTable *table;
563         guint32 *values;
564         guint32 tok;
565         MonoReflectionMethod *m;
566         int i;
567
568         mono_error_init (error);
569
570         if (!mb->override_methods)
571                 return TRUE;
572
573         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
574                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
575
576                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
577                 table->rows ++;
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);
582
583                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
584                 return_val_if_nok (error, FALSE);
585
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;
589                         break;
590                 case MONO_TABLE_METHOD:
591                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
592                         break;
593                 default:
594                         g_assert_not_reached ();
595                 }
596                 values [MONO_METHODIMPL_DECLARATION] = tok;
597         }
598
599         return TRUE;
600 }
601
602 #ifndef DISABLE_REFLECTION_EMIT
603 static gboolean
604 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
605 {
606         MONO_REQ_GC_UNSAFE_MODE;
607
608         MonoDynamicTable *table;
609         guint32 *values;
610         ReflectionMethodBuilder rmb;
611         int i;
612
613         mono_error_init (error);
614
615         if (!mono_reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
616             !mono_image_basic_method (&rmb, assembly, error))
617                 return FALSE;
618
619         mb->table_idx = *rmb.table_idx;
620
621         if (mb->dll) { /* It's a P/Invoke method */
622                 guint32 moduleref;
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];
627                 table->rows ++;
628                 alloc_table (table, table->rows);
629                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
630                 
631                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
632                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
633                 if (mb->dllentry) {
634                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry, error);
635                         return_val_if_nok (error, FALSE);
636                 } else {
637                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
638                         return_val_if_nok (error, FALSE);
639                 }
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];
644                         table->rows ++;
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;
648                 }
649         }
650
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);
657
658                         mono_image_get_generic_param_info (
659                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
660                 }
661         }
662
663         return TRUE;
664 }
665
666 static gboolean
667 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
668 {
669         MONO_REQ_GC_UNSAFE_MODE;
670
671         ReflectionMethodBuilder rmb;
672
673         if (!mono_reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
674                 return FALSE;
675
676         if (!mono_image_basic_method (&rmb, assembly, error))
677                 return FALSE;
678
679         mb->table_idx = *rmb.table_idx;
680
681         return TRUE;
682 }
683 #endif
684
685 static void
686 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
687 {
688         MONO_REQ_GC_UNSAFE_MODE;
689
690         mono_error_init (error);
691
692         MonoDynamicTable *table;
693         guint32 *values;
694
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);
707
708         if (fb->offset != -1) {
709                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
710                 table->rows ++;
711                 alloc_table (table, table->rows);
712                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
713                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
714                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
715         }
716         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
717                 MonoTypeEnum field_type = (MonoTypeEnum)0;
718                 table = &assembly->tables [MONO_TABLE_CONSTANT];
719                 table->rows ++;
720                 alloc_table (table, table->rows);
721                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
722                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
723                 values [MONO_CONSTANT_VALUE] = mono_dynimage_encode_constant (assembly, fb->def_value, &field_type);
724                 values [MONO_CONSTANT_TYPE] = field_type;
725                 values [MONO_CONSTANT_PADDING] = 0;
726         }
727         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
728                 guint32 rva_idx;
729                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
730                 table->rows ++;
731                 alloc_table (table, table->rows);
732                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
733                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
734                 /*
735                  * We store it in the code section because it's simpler for now.
736                  */
737                 if (fb->rva_data) {
738                         if (mono_array_length (fb->rva_data) >= 10)
739                                 stream_data_align (&assembly->code);
740                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
741                 } else
742                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
743                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
744         }
745         if (fb->marshal_info) {
746                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
747                 table->rows ++;
748                 alloc_table (table, table->rows);
749                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
750                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
751                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = mono_dynimage_save_encode_marshal_blob (assembly, fb->marshal_info, error);
752                 return_if_nok (error);
753         }
754 }
755
756 static void
757 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
758 {
759         MONO_REQ_GC_UNSAFE_MODE;
760
761         mono_error_init (error);
762
763         MonoDynamicTable *table;
764         guint32 *values;
765         guint num_methods = 0;
766         guint32 semaidx;
767
768         /* 
769          * we need to set things in the following tables:
770          * PROPERTYMAP (info already filled in _get_type_info ())
771          * PROPERTY    (rows already preallocated in _get_type_info ())
772          * METHOD      (method info already done with the generic method code)
773          * METHODSEMANTICS
774          * CONSTANT
775          */
776         table = &assembly->tables [MONO_TABLE_PROPERTY];
777         pb->table_idx = table->next_idx ++;
778         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
779         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
780         return_if_nok (error);
781         values [MONO_PROPERTY_FLAGS] = pb->attrs;
782         values [MONO_PROPERTY_TYPE] = mono_dynimage_save_encode_property_signature (assembly, pb, error);
783         return_if_nok (error);
784
785
786         /* FIXME: we still don't handle 'other' methods */
787         if (pb->get_method) num_methods ++;
788         if (pb->set_method) num_methods ++;
789
790         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
791         table->rows += num_methods;
792         alloc_table (table, table->rows);
793
794         if (pb->get_method) {
795                 semaidx = table->next_idx ++;
796                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
797                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
798                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
799                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
800         }
801         if (pb->set_method) {
802                 semaidx = table->next_idx ++;
803                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
804                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
805                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
806                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
807         }
808         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
809                 MonoTypeEnum field_type = (MonoTypeEnum)0;
810                 table = &assembly->tables [MONO_TABLE_CONSTANT];
811                 table->rows ++;
812                 alloc_table (table, table->rows);
813                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
814                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
815                 values [MONO_CONSTANT_VALUE] = mono_dynimage_encode_constant (assembly, pb->def_value, &field_type);
816                 values [MONO_CONSTANT_TYPE] = field_type;
817                 values [MONO_CONSTANT_PADDING] = 0;
818         }
819 }
820
821 static void
822 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
823 {
824         MONO_REQ_GC_UNSAFE_MODE;
825
826         MonoDynamicTable *table;
827         guint32 *values;
828         guint num_methods = 0;
829         guint32 semaidx;
830
831         /* 
832          * we need to set things in the following tables:
833          * EVENTMAP (info already filled in _get_type_info ())
834          * EVENT    (rows already preallocated in _get_type_info ())
835          * METHOD      (method info already done with the generic method code)
836          * METHODSEMANTICS
837          */
838         table = &assembly->tables [MONO_TABLE_EVENT];
839         eb->table_idx = table->next_idx ++;
840         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
841         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name, error);
842         return_if_nok (error);
843         values [MONO_EVENT_FLAGS] = eb->attrs;
844         MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
845         return_if_nok (error);
846         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
847
848         /*
849          * FIXME: we still don't handle 'other' methods 
850          */
851         if (eb->add_method) num_methods ++;
852         if (eb->remove_method) num_methods ++;
853         if (eb->raise_method) num_methods ++;
854
855         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
856         table->rows += num_methods;
857         alloc_table (table, table->rows);
858
859         if (eb->add_method) {
860                 semaidx = table->next_idx ++;
861                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
862                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
863                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
864                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
865         }
866         if (eb->remove_method) {
867                 semaidx = table->next_idx ++;
868                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
869                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
870                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
871                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
872         }
873         if (eb->raise_method) {
874                 semaidx = table->next_idx ++;
875                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
876                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
877                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
878                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
879         }
880 }
881
882 static void
883 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
884 {
885         MONO_REQ_GC_UNSAFE_MODE;
886
887         mono_error_init (error);
888
889         MonoDynamicTable *table;
890         guint32 num_constraints, i;
891         guint32 *values;
892         guint32 table_idx;
893
894         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
895         num_constraints = gparam->iface_constraints ?
896                 mono_array_length (gparam->iface_constraints) : 0;
897         table->rows += num_constraints;
898         if (gparam->base_type)
899                 table->rows++;
900         alloc_table (table, table->rows);
901
902         if (gparam->base_type) {
903                 table_idx = table->next_idx ++;
904                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
905
906                 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
907                 return_if_nok (error);
908                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
909                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
910         }
911
912         for (i = 0; i < num_constraints; i++) {
913                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
914                         gparam->iface_constraints, gpointer, i);
915
916                 table_idx = table->next_idx ++;
917                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
918
919                 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
920                 return_if_nok (error);
921
922                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
923                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
924         }
925 }
926
927 static void
928 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
929 {
930         MONO_REQ_GC_UNSAFE_MODE;
931
932         GenericParamTableEntry *entry;
933
934         /*
935          * The GenericParam table must be sorted according to the `owner' field.
936          * We need to do this sorting prior to writing the GenericParamConstraint
937          * table, since we have to use the final GenericParam table indices there
938          * and they must also be sorted.
939          */
940
941         entry = g_new0 (GenericParamTableEntry, 1);
942         entry->owner = owner;
943         /* FIXME: track where gen_params should be freed and remove the GC root as well */
944         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
945         entry->gparam = gparam;
946         
947         g_ptr_array_add (assembly->gen_params, entry);
948 }
949
950 static gboolean
951 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
952 {
953         MONO_REQ_GC_UNSAFE_MODE;
954
955         MonoDynamicTable *table;
956         MonoGenericParam *param;
957         guint32 *values;
958         guint32 table_idx;
959
960         mono_error_init (error);
961
962         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
963         table_idx = table->next_idx ++;
964         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
965
966         MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
967         return_val_if_nok (error, FALSE);
968
969         param = gparam_type->data.generic_param;
970
971         values [MONO_GENERICPARAM_OWNER] = entry->owner;
972         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
973         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
974         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
975
976         if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
977                 return FALSE;
978
979         encode_constraints (entry->gparam, table_idx, assembly, error);
980         return_val_if_nok (error, FALSE);
981
982         return TRUE;
983 }
984
985 static void
986 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
987 {
988         int i;
989
990         mono_ptr_array_append (*types, type);
991
992         if (!type->subtypes)
993                 return;
994
995         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
996                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
997                 collect_types (types, subtype);
998         }
999 }
1000
1001 static gint
1002 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
1003 {
1004         if ((*type1)->table_idx < (*type2)->table_idx)
1005                 return -1;
1006         else
1007                 if ((*type1)->table_idx > (*type2)->table_idx)
1008                         return 1;
1009         else
1010                 return 0;
1011 }
1012
1013 static gboolean
1014 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
1015         int i;
1016
1017         mono_error_init (error);
1018         if (!pinfo)
1019                 return TRUE;
1020         for (i = 0; i < mono_array_length (pinfo); ++i) {
1021                 MonoReflectionParamBuilder *pb;
1022                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
1023                 if (!pb)
1024                         continue;
1025                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
1026                         return FALSE;
1027         }
1028
1029         return TRUE;
1030 }
1031
1032 static gboolean
1033 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
1034         int i;
1035
1036         mono_error_init (error);
1037         
1038         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
1039                 return FALSE;
1040         if (tb->fields) {
1041                 for (i = 0; i < tb->num_fields; ++i) {
1042                         MonoReflectionFieldBuilder* fb;
1043                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
1044                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
1045                                 return FALSE;
1046                 }
1047         }
1048         if (tb->events) {
1049                 for (i = 0; i < mono_array_length (tb->events); ++i) {
1050                         MonoReflectionEventBuilder* eb;
1051                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
1052                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
1053                                 return FALSE;
1054                 }
1055         }
1056         if (tb->properties) {
1057                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
1058                         MonoReflectionPropertyBuilder* pb;
1059                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
1060                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
1061                                 return FALSE;
1062                 }
1063         }
1064         if (tb->ctors) {
1065                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
1066                         MonoReflectionCtorBuilder* cb;
1067                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
1068                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
1069                             !params_add_cattrs (assembly, cb->pinfo, error))
1070                                 return FALSE;
1071                 }
1072         }
1073
1074         if (tb->methods) {
1075                 for (i = 0; i < tb->num_methods; ++i) {
1076                         MonoReflectionMethodBuilder* mb;
1077                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
1078                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
1079                             !params_add_cattrs (assembly, mb->pinfo, error))
1080                                 return FALSE;
1081                 }
1082         }
1083
1084         if (tb->subtypes) {
1085                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1086                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
1087                                 return FALSE;
1088                 }
1089         }
1090
1091         return TRUE;
1092 }
1093
1094 static gboolean
1095 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
1096 {
1097         int i;
1098         
1099         mono_error_init (error);
1100
1101         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
1102                 return FALSE;
1103
1104         if (moduleb->global_methods) {
1105                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
1106                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
1107                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
1108                             !params_add_cattrs (assembly, mb->pinfo, error))
1109                                 return FALSE;
1110                 }
1111         }
1112
1113         if (moduleb->global_fields) {
1114                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
1115                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
1116                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
1117                                 return FALSE;
1118                 }
1119         }
1120         
1121         if (moduleb->types) {
1122                 for (i = 0; i < moduleb->num_types; ++i) {
1123                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
1124                                 return FALSE;
1125                 }
1126         }
1127
1128         return TRUE;
1129 }
1130
1131 static gboolean
1132 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly, MonoError *error)
1133 {
1134         MonoDynamicTable *table;
1135         guint32 *values;
1136         char blob_size [6];
1137         guchar hash [20];
1138         char *b = blob_size;
1139         char *dir, *path;
1140
1141         mono_error_init (error);
1142
1143         table = &assembly->tables [MONO_TABLE_FILE];
1144         table->rows++;
1145         alloc_table (table, table->rows);
1146         values = table->values + table->next_idx * MONO_FILE_SIZE;
1147         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
1148         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
1149         if (image_is_dynamic (module->image)) {
1150                 /* This depends on the fact that the main module is emitted last */
1151                 dir = mono_string_to_utf8_checked (((MonoReflectionModuleBuilder*)module)->assemblyb->dir, error);
1152                 return_val_if_nok (error, FALSE);
1153                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
1154         } else {
1155                 dir = NULL;
1156                 path = g_strdup (module->image->name);
1157         }
1158         mono_sha1_get_digest_from_file (path, hash);
1159         g_free (dir);
1160         g_free (path);
1161         mono_metadata_encode_value (20, b, &b);
1162         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1163         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
1164         table->next_idx ++;
1165         return TRUE;
1166 }
1167
1168 static void
1169 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1170 {
1171         MonoDynamicTable *table;
1172         int i;
1173
1174         mono_error_init (error);
1175
1176         table = &assembly->tables [MONO_TABLE_MODULE];
1177         mb->table_idx = table->next_idx ++;
1178         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name, error);
1179         return_if_nok (error);
1180         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
1181         i /= 16;
1182         ++i;
1183         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
1184         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
1185         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
1186         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
1187 }
1188
1189 static guint32
1190 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
1191         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
1192 {
1193         MonoDynamicTable *table;
1194         guint32 *values;
1195         guint32 visib, res;
1196
1197         visib = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1198         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
1199                 return 0;
1200
1201         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
1202         table->rows++;
1203         alloc_table (table, table->rows);
1204         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
1205
1206         values [MONO_EXP_TYPE_FLAGS] = mono_class_get_flags (klass);
1207         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
1208         if (klass->nested_in)
1209                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
1210         else
1211                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
1212         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1213         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1214
1215         res = table->next_idx;
1216
1217         table->next_idx ++;
1218
1219         /* Emit nested types */
1220         if (klass->ext && klass->ext->nested_classes) {
1221                 GList *tmp;
1222
1223                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
1224                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
1225         }
1226
1227         return res;
1228 }
1229
1230 static void
1231 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
1232                               guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
1233                               MonoError *error)
1234 {
1235         MonoClass *klass;
1236         guint32 idx, i;
1237
1238         mono_error_init (error);
1239
1240         MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
1241         return_if_nok (error);
1242
1243         klass = mono_class_from_mono_type (t);
1244
1245         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
1246
1247         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
1248                                                                                                    parent_index, assembly);
1249
1250         /* 
1251          * Emit nested types
1252          * We need to do this ourselves since klass->nested_classes is not set up.
1253          */
1254         if (tb->subtypes) {
1255                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1256                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
1257                         return_if_nok (error);
1258                 }
1259         }
1260 }
1261
1262 static void
1263 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
1264         guint32 module_index, MonoDynamicImage *assembly)
1265 {
1266         MonoImage *image = module->image;
1267         MonoTableInfo  *t;
1268         guint32 i;
1269
1270         t = &image->tables [MONO_TABLE_TYPEDEF];
1271
1272         for (i = 0; i < t->rows; ++i) {
1273                 MonoError error;
1274                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
1275                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1276
1277                 if (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_PUBLIC)
1278                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
1279         }
1280 }
1281
1282 static void
1283 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
1284 {
1285         MonoDynamicTable *table;
1286         guint32 *values;
1287         guint32 scope, scope_idx, impl, current_idx;
1288         gboolean forwarder = TRUE;
1289         gpointer iter = NULL;
1290         MonoClass *nested;
1291
1292         if (klass->nested_in) {
1293                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
1294                 forwarder = FALSE;
1295         } else {
1296                 scope = mono_reflection_resolution_scope_from_image (assembly, klass->image);
1297                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
1298                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
1299                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
1300         }
1301
1302         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
1303
1304         table->rows++;
1305         alloc_table (table, table->rows);
1306         current_idx = table->next_idx;
1307         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
1308
1309         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
1310         values [MONO_EXP_TYPE_TYPEDEF] = 0;
1311         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
1312         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1313         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1314
1315         table->next_idx++;
1316
1317         while ((nested = mono_class_get_nested_types (klass, &iter)))
1318                 add_exported_type (assemblyb, assembly, nested, current_idx);
1319 }
1320
1321 static void
1322 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
1323 {
1324         MonoError error;
1325         MonoClass *klass;
1326         int i;
1327
1328         if (!assemblyb->type_forwarders)
1329                 return;
1330
1331         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
1332                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
1333                 MonoType *type;
1334                 if (!t)
1335                         continue;
1336
1337                 type = mono_reflection_type_get_handle (t, &error);
1338                 mono_error_assert_ok (&error);
1339                 g_assert (type);
1340
1341                 klass = mono_class_from_mono_type (type);
1342
1343                 add_exported_type (assemblyb, assembly, klass, 0);
1344         }
1345 }
1346
1347 #define align_pointer(base,p)\
1348         do {\
1349                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1350                 if (__diff & 3)\
1351                         (p) += 4 - (__diff & 3);\
1352         } while (0)
1353
1354 static int
1355 compare_constants (const void *a, const void *b)
1356 {
1357         const guint32 *a_values = (const guint32 *)a;
1358         const guint32 *b_values = (const guint32 *)b;
1359         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
1360 }
1361
1362 static int
1363 compare_semantics (const void *a, const void *b)
1364 {
1365         const guint32 *a_values = (const guint32 *)a;
1366         const guint32 *b_values = (const guint32 *)b;
1367         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
1368         if (assoc)
1369                 return assoc;
1370         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
1371 }
1372
1373 static int
1374 compare_custom_attrs (const void *a, const void *b)
1375 {
1376         const guint32 *a_values = (const guint32 *)a;
1377         const guint32 *b_values = (const guint32 *)b;
1378
1379         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
1380 }
1381
1382 static int
1383 compare_field_marshal (const void *a, const void *b)
1384 {
1385         const guint32 *a_values = (const guint32 *)a;
1386         const guint32 *b_values = (const guint32 *)b;
1387
1388         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
1389 }
1390
1391 static int
1392 compare_nested (const void *a, const void *b)
1393 {
1394         const guint32 *a_values = (const guint32 *)a;
1395         const guint32 *b_values = (const guint32 *)b;
1396
1397         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
1398 }
1399
1400 static int
1401 compare_genericparam (const void *a, const void *b)
1402 {
1403         MonoError error;
1404         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
1405         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
1406
1407         if ((*b_entry)->owner == (*a_entry)->owner) {
1408                 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
1409                 mono_error_assert_ok (&error);
1410                 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
1411                 mono_error_assert_ok (&error);
1412                 return 
1413                         mono_type_get_generic_param_num (a_type) -
1414                         mono_type_get_generic_param_num (b_type);
1415         } else
1416                 return (*a_entry)->owner - (*b_entry)->owner;
1417 }
1418
1419 static int
1420 compare_declsecurity_attrs (const void *a, const void *b)
1421 {
1422         const guint32 *a_values = (const guint32 *)a;
1423         const guint32 *b_values = (const guint32 *)b;
1424
1425         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
1426 }
1427
1428 static int
1429 compare_interface_impl (const void *a, const void *b)
1430 {
1431         const guint32 *a_values = (const guint32 *)a;
1432         const guint32 *b_values = (const guint32 *)b;
1433
1434         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
1435         if (klass)
1436                 return klass;
1437
1438         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
1439 }
1440
1441 struct StreamDesc {
1442         const char *name;
1443         MonoDynamicStream *stream;
1444 };
1445
1446 /*
1447  * build_compressed_metadata() fills in the blob of data that represents the 
1448  * raw metadata as it will be saved in the PE file. The five streams are output 
1449  * and the metadata tables are comnpressed from the guint32 array representation, 
1450  * to the compressed on-disk format.
1451  */
1452 static gboolean
1453 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
1454 {
1455         MonoDynamicTable *table;
1456         int i;
1457         guint64 valid_mask = 0;
1458         guint64 sorted_mask;
1459         guint32 heapt_size = 0;
1460         guint32 meta_size = 256; /* allow for header and other stuff */
1461         guint32 table_offset;
1462         guint32 ntables = 0;
1463         guint64 *int64val;
1464         guint32 *int32val;
1465         guint16 *int16val;
1466         MonoImage *meta;
1467         unsigned char *p;
1468         struct StreamDesc stream_desc [5];
1469
1470         mono_error_init (error);
1471
1472         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
1473         for (i = 0; i < assembly->gen_params->len; i++) {
1474                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
1475                 if (!write_generic_param_entry (assembly, entry, error))
1476                         return FALSE;
1477         }
1478
1479         stream_desc [0].name  = "#~";
1480         stream_desc [0].stream = &assembly->tstream;
1481         stream_desc [1].name  = "#Strings";
1482         stream_desc [1].stream = &assembly->sheap;
1483         stream_desc [2].name  = "#US";
1484         stream_desc [2].stream = &assembly->us;
1485         stream_desc [3].name  = "#Blob";
1486         stream_desc [3].stream = &assembly->blob;
1487         stream_desc [4].name  = "#GUID";
1488         stream_desc [4].stream = &assembly->guid;
1489         
1490         /* tables that are sorted */
1491         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
1492                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
1493                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
1494                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
1495                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
1496                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
1497                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
1498         
1499         /* Compute table sizes */
1500         /* the MonoImage has already been created in mono_reflection_dynimage_basic_init() */
1501         meta = &assembly->image;
1502
1503         /* sizes should be multiple of 4 */
1504         mono_dynstream_data_align (&assembly->blob);
1505         mono_dynstream_data_align (&assembly->guid);
1506         mono_dynstream_data_align (&assembly->sheap);
1507         mono_dynstream_data_align (&assembly->us);
1508
1509         /* Setup the info used by compute_sizes () */
1510         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
1511         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
1512         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
1513
1514         meta_size += assembly->blob.index;
1515         meta_size += assembly->guid.index;
1516         meta_size += assembly->sheap.index;
1517         meta_size += assembly->us.index;
1518
1519         for (i=0; i < MONO_TABLE_NUM; ++i)
1520                 meta->tables [i].rows = assembly->tables [i].rows;
1521         
1522         for (i = 0; i < MONO_TABLE_NUM; i++){
1523                 if (meta->tables [i].rows == 0)
1524                         continue;
1525                 valid_mask |= (guint64)1 << i;
1526                 ntables ++;
1527                 meta->tables [i].row_size = mono_metadata_compute_size (
1528                         meta, i, &meta->tables [i].size_bitfield);
1529                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
1530         }
1531         heapt_size += 24; /* #~ header size */
1532         heapt_size += ntables * 4;
1533         /* make multiple of 4 */
1534         heapt_size += 3;
1535         heapt_size &= ~3;
1536         meta_size += heapt_size;
1537         meta->raw_metadata = (char *)g_malloc0 (meta_size);
1538         p = (unsigned char*)meta->raw_metadata;
1539         /* the metadata signature */
1540         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
1541         /* version numbers and 4 bytes reserved */
1542         int16val = (guint16*)p;
1543         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
1544         *int16val = GUINT16_TO_LE (meta->md_version_minor);
1545         p += 8;
1546         /* version string */
1547         int32val = (guint32*)p;
1548         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
1549         p += 4;
1550         memcpy (p, meta->version, strlen (meta->version));
1551         p += GUINT32_FROM_LE (*int32val);
1552         align_pointer (meta->raw_metadata, p);
1553         int16val = (guint16*)p;
1554         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
1555         *int16val = GUINT16_TO_LE (5); /* number of streams */
1556         p += 4;
1557
1558         /*
1559          * write the stream info.
1560          */
1561         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
1562         table_offset += 3; table_offset &= ~3;
1563
1564         assembly->tstream.index = heapt_size;
1565         for (i = 0; i < 5; ++i) {
1566                 int32val = (guint32*)p;
1567                 stream_desc [i].stream->offset = table_offset;
1568                 *int32val++ = GUINT32_TO_LE (table_offset);
1569                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
1570                 table_offset += GUINT32_FROM_LE (*int32val);
1571                 table_offset += 3; table_offset &= ~3;
1572                 p += 8;
1573                 strcpy ((char*)p, stream_desc [i].name);
1574                 p += strlen (stream_desc [i].name) + 1;
1575                 align_pointer (meta->raw_metadata, p);
1576         }
1577         /* 
1578          * now copy the data, the table stream header and contents goes first.
1579          */
1580         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
1581         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
1582         int32val = (guint32*)p;
1583         *int32val = GUINT32_TO_LE (0); /* reserved */
1584         p += 4;
1585
1586         *p++ = 2; /* version */
1587         *p++ = 0;
1588
1589         if (meta->idx_string_wide)
1590                 *p |= 0x01;
1591         if (meta->idx_guid_wide)
1592                 *p |= 0x02;
1593         if (meta->idx_blob_wide)
1594                 *p |= 0x04;
1595         ++p;
1596         *p++ = 1; /* reserved */
1597         int64val = (guint64*)p;
1598         *int64val++ = GUINT64_TO_LE (valid_mask);
1599         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
1600         p += 16;
1601         int32val = (guint32*)p;
1602         for (i = 0; i < MONO_TABLE_NUM; i++){
1603                 if (meta->tables [i].rows == 0)
1604                         continue;
1605                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
1606         }
1607         p = (unsigned char*)int32val;
1608
1609         /* sort the tables that still need sorting */
1610         table = &assembly->tables [MONO_TABLE_CONSTANT];
1611         if (table->rows)
1612                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
1613         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1614         if (table->rows)
1615                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
1616         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1617         if (table->rows)
1618                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
1619         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1620         if (table->rows)
1621                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
1622         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1623         if (table->rows)
1624                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
1625         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
1626         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1627         if (table->rows)
1628                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
1629         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1630         if (table->rows)
1631                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
1632
1633         /* compress the tables */
1634         for (i = 0; i < MONO_TABLE_NUM; i++){
1635                 int row, col;
1636                 guint32 *values;
1637                 guint32 bitfield = meta->tables [i].size_bitfield;
1638                 if (!meta->tables [i].rows)
1639                         continue;
1640                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
1641                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
1642                 meta->tables [i].base = (char*)p;
1643                 for (row = 1; row <= meta->tables [i].rows; ++row) {
1644                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
1645                         for (col = 0; col < assembly->tables [i].columns; ++col) {
1646                                 switch (mono_metadata_table_size (bitfield, col)) {
1647                                 case 1:
1648                                         *p++ = values [col];
1649                                         break;
1650                                 case 2:
1651                                         *p++ = values [col] & 0xff;
1652                                         *p++ = (values [col] >> 8) & 0xff;
1653                                         break;
1654                                 case 4:
1655                                         *p++ = values [col] & 0xff;
1656                                         *p++ = (values [col] >> 8) & 0xff;
1657                                         *p++ = (values [col] >> 16) & 0xff;
1658                                         *p++ = (values [col] >> 24) & 0xff;
1659                                         break;
1660                                 default:
1661                                         g_assert_not_reached ();
1662                                 }
1663                         }
1664                 }
1665                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
1666         }
1667         
1668         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
1669         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
1670         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
1671         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
1672         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
1673
1674         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
1675
1676         return TRUE;
1677 }
1678
1679 /*
1680  * Some tables in metadata need to be sorted according to some criteria, but
1681  * when methods and fields are first created with reflection, they may be assigned a token
1682  * that doesn't correspond to the final token they will get assigned after the sorting.
1683  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
1684  * with the reflection objects that represent them. Once all the tables are set up, the 
1685  * reflection objects will contains the correct table index. fixup_method() will fixup the
1686  * tokens for the method with ILGenerator @ilgen.
1687  */
1688 static void
1689 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
1690 {
1691         guint32 code_idx = GPOINTER_TO_UINT (value);
1692         MonoReflectionILTokenInfo *iltoken;
1693         MonoReflectionTypeBuilder *tb;
1694         MonoReflectionArrayMethod *am;
1695         guint32 i, idx = 0;
1696         unsigned char *target;
1697
1698         for (i = 0; i < ilgen->num_token_fixups; ++i) {
1699                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
1700                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
1701                 switch (target [3]) {
1702                 case MONO_TABLE_FIELD:
1703                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
1704                                 g_assert_not_reached ();
1705                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
1706                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
1707                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
1708                         } else {
1709                                 g_assert_not_reached ();
1710                         }
1711                         break;
1712                 case MONO_TABLE_METHOD:
1713                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
1714                                 g_assert_not_reached ();
1715                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
1716                                 g_assert_not_reached ();
1717                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
1718                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
1719                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
1720                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
1721                         } else {
1722                                 g_assert_not_reached ();
1723                         }
1724                         break;
1725                 case MONO_TABLE_TYPEDEF:
1726                         if (!strcmp (iltoken->member->vtable->klass->name, "TypeBuilder")) {
1727                                 g_assert_not_reached ();
1728                         } else if (!strcmp (iltoken->member->vtable->klass->name, "RuntimeType")) {
1729                                 MonoClass *k = mono_class_from_mono_type (((MonoReflectionType*)iltoken->member)->type);
1730                                 MonoObject *obj = mono_class_get_ref_info (k);
1731                                 g_assert (obj);
1732                                 g_assert (!strcmp (obj->vtable->klass->name, "TypeBuilder"));
1733                                 tb = (MonoReflectionTypeBuilder*)obj;
1734                                 idx = tb->table_idx;
1735                         } else {
1736                                 g_assert_not_reached ();
1737                         }
1738                         break;
1739                 case MONO_TABLE_MEMBERREF:
1740                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
1741                                 am = (MonoReflectionArrayMethod*)iltoken->member;
1742                                 idx = am->table_idx;
1743                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
1744                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
1745                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
1746                                 g_assert (mono_class_is_ginst (m->klass) || m->klass->generic_container);
1747                                 continue;
1748                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
1749                                 g_assert_not_reached ();
1750                                 continue;
1751                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
1752                                 continue;
1753                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
1754                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
1755                                 g_assert_not_reached ();
1756                                 continue;
1757                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
1758                                 g_assert_not_reached ();
1759                                 continue;
1760                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
1761                                 g_assert_not_reached ();
1762                                 continue;
1763                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
1764                                 g_assert_not_reached ();
1765                                 continue;
1766                         } else {
1767                                 g_assert_not_reached ();
1768                         }
1769                         break;
1770                 case MONO_TABLE_METHODSPEC:
1771                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
1772                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
1773                                 g_assert (mono_method_signature (m)->generic_param_count);
1774                                 continue;
1775                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
1776                                 g_assert_not_reached ();
1777                                 continue;
1778                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
1779                                 g_assert_not_reached ();
1780                                 continue;
1781                         } else {
1782                                 g_assert_not_reached ();
1783                         }
1784                         break;
1785                 case MONO_TABLE_TYPESPEC:
1786                         if (!strcmp (iltoken->member->vtable->klass->name, "RuntimeType")) {
1787                                 continue;
1788                         } else {
1789                                 g_assert_not_reached ();
1790                         }
1791                         break;
1792                 default:
1793                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
1794                 }
1795                 target [0] = idx & 0xff;
1796                 target [1] = (idx >> 8) & 0xff;
1797                 target [2] = (idx >> 16) & 0xff;
1798         }
1799 }
1800
1801 /*
1802  * fixup_cattrs:
1803  *
1804  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
1805  * value is not known when the table is emitted.
1806  */
1807 static void
1808 fixup_cattrs (MonoDynamicImage *assembly)
1809 {
1810         MonoDynamicTable *table;
1811         guint32 *values;
1812         guint32 type, i, idx, token;
1813         MonoObject *ctor;
1814
1815         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1816
1817         for (i = 0; i < table->rows; ++i) {
1818                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
1819
1820                 type = values [MONO_CUSTOM_ATTR_TYPE];
1821                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
1822                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
1823                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
1824                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
1825                         g_assert (ctor);
1826
1827                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
1828                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
1829                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
1830                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1831                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
1832                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
1833                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
1834                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1835                         }
1836                 }
1837         }
1838 }
1839
1840 static gboolean
1841 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation, MonoError *error)
1842 {
1843         MonoDynamicTable *table;
1844         guint32 *values;
1845
1846         mono_error_init (error);
1847
1848         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
1849         table->rows++;
1850         alloc_table (table, table->rows);
1851         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
1852         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
1853         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
1854         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name, error);
1855         return_val_if_nok (error, FALSE);
1856         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
1857         table->next_idx++;
1858         return TRUE;
1859 }
1860
1861 static gboolean
1862 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, MonoError *error)
1863 {
1864         MonoDynamicTable *table;
1865         guint32 *values;
1866         char blob_size [6];
1867         guchar hash [20];
1868         char *b = blob_size;
1869         char *name, *sname;
1870         guint32 idx, offset;
1871
1872         mono_error_init (error);
1873
1874         if (rsrc->filename) {
1875                 name = mono_string_to_utf8_checked (rsrc->filename, error);
1876                 return_val_if_nok (error, FALSE);
1877                 sname = g_path_get_basename (name);
1878         
1879                 table = &assembly->tables [MONO_TABLE_FILE];
1880                 table->rows++;
1881                 alloc_table (table, table->rows);
1882                 values = table->values + table->next_idx * MONO_FILE_SIZE;
1883                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
1884                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
1885                 g_free (sname);
1886
1887                 mono_sha1_get_digest_from_file (name, hash);
1888                 mono_metadata_encode_value (20, b, &b);
1889                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1890                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
1891                 g_free (name);
1892                 idx = table->next_idx++;
1893                 rsrc->offset = 0;
1894                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
1895         } else {
1896                 char sizebuf [4];
1897                 char *data;
1898                 guint len;
1899                 if (rsrc->data) {
1900                         data = mono_array_addr (rsrc->data, char, 0);
1901                         len = mono_array_length (rsrc->data);
1902                 } else {
1903                         data = NULL;
1904                         len = 0;
1905                 }
1906                 offset = len;
1907                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
1908                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
1909                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
1910                 mono_image_add_stream_data (&assembly->resources, data, len);
1911
1912                 if (!mb->is_main)
1913                         /* 
1914                          * The entry should be emitted into the MANIFESTRESOURCE table of 
1915                          * the main module, but that needs to reference the FILE table
1916                          * which isn't emitted yet.
1917                          */
1918                         return TRUE;
1919                 else
1920                         idx = 0;
1921         }
1922
1923         return assembly_add_resource_manifest (mb, assembly, rsrc, idx, error);
1924 }
1925
1926 static gboolean
1927 set_version_from_string (MonoString *version, guint32 *values, MonoError *error)
1928 {
1929         gchar *ver, *p, *str;
1930         guint32 i;
1931         
1932         mono_error_init (error);
1933
1934         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
1935         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
1936         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
1937         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
1938         if (!version)
1939                 return TRUE;
1940         ver = str = mono_string_to_utf8_checked (version, error);
1941         return_val_if_nok (error, FALSE);
1942         for (i = 0; i < 4; ++i) {
1943                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
1944                 switch (*p) {
1945                 case '.':
1946                         p++;
1947                         break;
1948                 case '*':
1949                         /* handle Revision and Build */
1950                         p++;
1951                         break;
1952                 }
1953                 ver = p;
1954         }
1955         g_free (str);
1956         return TRUE;
1957 }
1958
1959 static guint32
1960 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
1961         gsize len;
1962         guint32 token = 0;
1963         char blob_size [6];
1964         char *b = blob_size;
1965
1966         if (!pkey)
1967                 return token;
1968
1969         len = mono_array_length (pkey);
1970         mono_metadata_encode_value (len, b, &b);
1971         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
1972         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
1973
1974         assembly->public_key = (guint8 *)g_malloc (len);
1975         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
1976         assembly->public_key_len = len;
1977
1978         /* Special case: check for ECMA key (16 bytes) */
1979         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
1980                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
1981                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
1982         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
1983                 /* minimum key size (in 2.0) is 384 bits */
1984                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
1985         } else {
1986                 /* FIXME - verifier */
1987                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
1988                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
1989         }
1990         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
1991
1992         return token;
1993 }
1994
1995 static gboolean
1996 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
1997 {
1998         MonoDynamicTable *table;
1999         MonoDynamicImage *assembly;
2000         MonoReflectionAssemblyBuilder *assemblyb;
2001         MonoDomain *domain;
2002         guint32 *values;
2003         int i;
2004         guint32 module_index;
2005
2006         mono_error_init (error);
2007
2008         assemblyb = moduleb->assemblyb;
2009         assembly = moduleb->dynamic_image;
2010         domain = mono_object_domain (assemblyb);
2011
2012         /* Emit ASSEMBLY table */
2013         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
2014         alloc_table (table, 1);
2015         values = table->values + MONO_ASSEMBLY_SIZE;
2016         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
2017         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name, error);
2018         return_val_if_nok (error, FALSE);
2019         if (assemblyb->culture) {
2020                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture, error);
2021                 return_val_if_nok (error, FALSE);
2022         } else {
2023                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
2024         }
2025         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
2026         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
2027         if (!set_version_from_string (assemblyb->version, values, error))
2028                 return FALSE;
2029
2030         /* Emit FILE + EXPORTED_TYPE table */
2031         module_index = 0;
2032         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
2033                 int j;
2034                 MonoReflectionModuleBuilder *file_module = 
2035                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
2036                 if (file_module != moduleb) {
2037                         if (!mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly, error))
2038                                 return FALSE;
2039                         module_index ++;
2040                         if (file_module->types) {
2041                                 for (j = 0; j < file_module->num_types; ++j) {
2042                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
2043                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
2044                                         return_val_if_nok (error, FALSE);
2045                                 }
2046                         }
2047                 }
2048         }
2049         if (assemblyb->loaded_modules) {
2050                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
2051                         MonoReflectionModule *file_module = 
2052                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
2053                         if (!mono_image_fill_file_table (domain, file_module, assembly, error))
2054                                 return FALSE;
2055                         module_index ++;
2056                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
2057                 }
2058         }
2059         if (assemblyb->type_forwarders)
2060                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
2061
2062         /* Emit MANIFESTRESOURCE table */
2063         module_index = 0;
2064         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
2065                 int j;
2066                 MonoReflectionModuleBuilder *file_module = 
2067                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
2068                 /* The table for the main module is emitted later */
2069                 if (file_module != moduleb) {
2070                         module_index ++;
2071                         if (file_module->resources) {
2072                                 int len = mono_array_length (file_module->resources);
2073                                 for (j = 0; j < len; ++j) {
2074                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
2075                                         if (!assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS), error))
2076                                                 return FALSE;
2077                                 }
2078                         }
2079                 }
2080         }
2081         return TRUE;
2082 }
2083
2084 #ifndef DISABLE_REFLECTION_EMIT_SAVE
2085
2086 /*
2087  * Insert into the metadata tables all the info about the TypeBuilder tb.
2088  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2089  */
2090 static gboolean
2091 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
2092 {
2093         MonoDynamicTable *table;
2094         guint *values;
2095         int i, is_object = 0, is_system = 0;
2096         char *n;
2097
2098         mono_error_init (error);
2099
2100         table = &assembly->tables [MONO_TABLE_TYPEDEF];
2101         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2102         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2103         n = mono_string_to_utf8_checked (tb->name, error);
2104         return_val_if_nok (error, FALSE);
2105         if (strcmp (n, "Object") == 0)
2106                 is_object++;
2107         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2108         g_free (n);
2109         n = mono_string_to_utf8_checked (tb->nspace, error);
2110         return_val_if_nok (error, FALSE);
2111         if (strcmp (n, "System") == 0)
2112                 is_system++;
2113         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2114         g_free (n);
2115         if (tb->parent && !(is_system && is_object) && 
2116                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2117                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
2118                 return_val_if_nok (error, FALSE);
2119                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
2120         } else {
2121                 values [MONO_TYPEDEF_EXTENDS] = 0;
2122         }
2123         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2124         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2125
2126         /*
2127          * if we have explicitlayout or sequentiallayouts, output data in the
2128          * ClassLayout table.
2129          */
2130         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2131                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
2132                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2133                 table->rows++;
2134                 alloc_table (table, table->rows);
2135                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2136                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2137                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2138                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2139         }
2140
2141         /* handle interfaces */
2142         if (tb->interfaces) {
2143                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2144                 i = table->rows;
2145                 table->rows += mono_array_length (tb->interfaces);
2146                 alloc_table (table, table->rows);
2147                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2148                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2149                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2150                         MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
2151                         return_val_if_nok (error, FALSE);
2152                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2153                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
2154                         values += MONO_INTERFACEIMPL_SIZE;
2155                 }
2156         }
2157
2158         /* handle fields */
2159         if (tb->fields) {
2160                 table = &assembly->tables [MONO_TABLE_FIELD];
2161                 table->rows += tb->num_fields;
2162                 alloc_table (table, table->rows);
2163                 for (i = 0; i < tb->num_fields; ++i) {
2164                         mono_image_get_field_info (
2165                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
2166                         return_val_if_nok (error, FALSE);
2167                 }
2168         }
2169
2170         /* handle constructors */
2171         if (tb->ctors) {
2172                 table = &assembly->tables [MONO_TABLE_METHOD];
2173                 table->rows += mono_array_length (tb->ctors);
2174                 alloc_table (table, table->rows);
2175                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2176                         if (!mono_image_get_ctor_info (domain,
2177                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
2178                                                        assembly, error))
2179                                 return FALSE;
2180                 }
2181         }
2182
2183         /* handle methods */
2184         if (tb->methods) {
2185                 table = &assembly->tables [MONO_TABLE_METHOD];
2186                 table->rows += tb->num_methods;
2187                 alloc_table (table, table->rows);
2188                 for (i = 0; i < tb->num_methods; ++i) {
2189                         if (!mono_image_get_method_info (
2190                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
2191                                 return FALSE;
2192                 }
2193         }
2194
2195         /* Do the same with properties etc.. */
2196         if (tb->events && mono_array_length (tb->events)) {
2197                 table = &assembly->tables [MONO_TABLE_EVENT];
2198                 table->rows += mono_array_length (tb->events);
2199                 alloc_table (table, table->rows);
2200                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2201                 table->rows ++;
2202                 alloc_table (table, table->rows);
2203                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2204                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2205                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2206                 for (i = 0; i < mono_array_length (tb->events); ++i) {
2207                         mono_image_get_event_info (
2208                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
2209                         return_val_if_nok (error, FALSE);
2210                 }
2211         }
2212         if (tb->properties && mono_array_length (tb->properties)) {
2213                 table = &assembly->tables [MONO_TABLE_PROPERTY];
2214                 table->rows += mono_array_length (tb->properties);
2215                 alloc_table (table, table->rows);
2216                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2217                 table->rows ++;
2218                 alloc_table (table, table->rows);
2219                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2220                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2221                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2222                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2223                         mono_image_get_property_info (
2224                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
2225                         return_val_if_nok (error, FALSE);
2226                 }
2227         }
2228
2229         /* handle generic parameters */
2230         if (tb->generic_params) {
2231                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2232                 table->rows += mono_array_length (tb->generic_params);
2233                 alloc_table (table, table->rows);
2234                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2235                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2236
2237                         mono_image_get_generic_param_info (
2238                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2239                 }
2240         }
2241
2242         mono_image_add_decl_security (assembly, 
2243                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2244
2245         if (tb->subtypes) {
2246                 MonoDynamicTable *ntable;
2247                 
2248                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2249                 ntable->rows += mono_array_length (tb->subtypes);
2250                 alloc_table (ntable, ntable->rows);
2251                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2252
2253                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2254                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2255
2256                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2257                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2258                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2259                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2260                                 mono_string_to_utf8 (tb->name), tb->table_idx,
2261                                 ntable->next_idx, ntable->rows);*/
2262                         values += MONO_NESTED_CLASS_SIZE;
2263                         ntable->next_idx++;
2264                 }
2265         }
2266
2267         return TRUE;
2268 }
2269
2270
2271 /*
2272  * mono_image_build_metadata() will fill the info in all the needed metadata tables
2273  * for the modulebuilder @moduleb.
2274  * At the end of the process, method and field tokens are fixed up and the 
2275  * on-disk compressed metadata representation is created.
2276  * Return TRUE on success, or FALSE on failure and sets @error
2277  */
2278 gboolean
2279 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
2280 {
2281         MonoDynamicTable *table;
2282         MonoDynamicImage *assembly;
2283         MonoReflectionAssemblyBuilder *assemblyb;
2284         MonoDomain *domain;
2285         MonoPtrArray types;
2286         guint32 *values;
2287         int i, j;
2288
2289         mono_error_init (error);
2290
2291         assemblyb = moduleb->assemblyb;
2292         assembly = moduleb->dynamic_image;
2293         domain = mono_object_domain (assemblyb);
2294
2295         if (assembly->text_rva)
2296                 return TRUE;
2297
2298         assembly->text_rva = START_TEXT_RVA;
2299
2300         if (moduleb->is_main) {
2301                 mono_image_emit_manifest (moduleb, error);
2302                 return_val_if_nok (error, FALSE);
2303         }
2304
2305         table = &assembly->tables [MONO_TABLE_TYPEDEF];
2306         table->rows = 1; /* .<Module> */
2307         table->next_idx++;
2308         alloc_table (table, table->rows);
2309         /*
2310          * Set the first entry.
2311          */
2312         values = table->values + table->columns;
2313         values [MONO_TYPEDEF_FLAGS] = 0;
2314         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
2315         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
2316         values [MONO_TYPEDEF_EXTENDS] = 0;
2317         values [MONO_TYPEDEF_FIELD_LIST] = 1;
2318         values [MONO_TYPEDEF_METHOD_LIST] = 1;
2319
2320         /* 
2321          * handle global methods 
2322          * FIXME: test what to do when global methods are defined in multiple modules.
2323          */
2324         if (moduleb->global_methods) {
2325                 table = &assembly->tables [MONO_TABLE_METHOD];
2326                 table->rows += mono_array_length (moduleb->global_methods);
2327                 alloc_table (table, table->rows);
2328                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
2329                         if (!mono_image_get_method_info (
2330                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
2331                                 goto leave;
2332                 }
2333         }
2334         if (moduleb->global_fields) {
2335                 table = &assembly->tables [MONO_TABLE_FIELD];
2336                 table->rows += mono_array_length (moduleb->global_fields);
2337                 alloc_table (table, table->rows);
2338                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
2339                         mono_image_get_field_info (
2340                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
2341                                 error);
2342                         if (!is_ok (error))
2343                                 goto leave;
2344                 }
2345         }
2346
2347         table = &assembly->tables [MONO_TABLE_MODULE];
2348         alloc_table (table, 1);
2349         mono_image_fill_module_table (domain, moduleb, assembly, error);
2350         if (!is_ok (error))
2351                 goto leave;
2352
2353         /* Collect all types into a list sorted by their table_idx */
2354         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
2355
2356         if (moduleb->types)
2357                 for (i = 0; i < moduleb->num_types; ++i) {
2358                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
2359                         collect_types (&types, type);
2360                 }
2361
2362         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
2363         table = &assembly->tables [MONO_TABLE_TYPEDEF];
2364         table->rows += mono_ptr_array_size (types);
2365         alloc_table (table, table->rows);
2366
2367         /*
2368          * Emit type names + namespaces at one place inside the string heap,
2369          * so load_class_names () needs to touch fewer pages.
2370          */
2371         for (i = 0; i < mono_ptr_array_size (types); ++i) {
2372                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
2373                 string_heap_insert_mstring (&assembly->sheap, tb->nspace, error);
2374                 if (!is_ok (error))
2375                         goto leave_types;
2376         }
2377         for (i = 0; i < mono_ptr_array_size (types); ++i) {
2378                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
2379                 string_heap_insert_mstring (&assembly->sheap, tb->name, error);
2380                 if (!is_ok (error))
2381                         goto leave_types;
2382         }
2383
2384         for (i = 0; i < mono_ptr_array_size (types); ++i) {
2385                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
2386                 if (!mono_image_get_type_info (domain, type, assembly, error))
2387                         goto leave_types;
2388         }
2389
2390         /* 
2391          * table->rows is already set above and in mono_image_fill_module_table.
2392          */
2393         /* add all the custom attributes at the end, once all the indexes are stable */
2394         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
2395                 goto leave_types;
2396
2397         /* CAS assembly permissions */
2398         if (assemblyb->permissions_minimum)
2399                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
2400         if (assemblyb->permissions_optional)
2401                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
2402         if (assemblyb->permissions_refused)
2403                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
2404
2405         if (!module_add_cattrs (assembly, moduleb, error))
2406                 goto leave_types;
2407
2408         /* fixup tokens */
2409         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
2410
2411         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
2412          * the final tokens and don't need another fixup pass. */
2413
2414         if (moduleb->global_methods) {
2415                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
2416                         MonoReflectionMethodBuilder *mb = mono_array_get (
2417                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
2418                         if (!mono_image_add_methodimpl (assembly, mb, error))
2419                                 goto leave_types;
2420                 }
2421         }
2422
2423         for (i = 0; i < mono_ptr_array_size (types); ++i) {
2424                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
2425                 if (type->methods) {
2426                         for (j = 0; j < type->num_methods; ++j) {
2427                                 MonoReflectionMethodBuilder *mb = mono_array_get (
2428                                         type->methods, MonoReflectionMethodBuilder*, j);
2429
2430                                 if (!mono_image_add_methodimpl (assembly, mb, error))
2431                                         goto leave_types;
2432                         }
2433                 }
2434         }
2435
2436         fixup_cattrs (assembly);
2437
2438 leave_types:
2439         mono_ptr_array_destroy (types);
2440 leave:
2441
2442         return mono_error_ok (error);
2443 }
2444
2445 #else /* DISABLE_REFLECTION_EMIT_SAVE */
2446
2447 gboolean
2448 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
2449 {
2450         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
2451 }
2452
2453 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
2454
2455 #ifndef DISABLE_REFLECTION_EMIT_SAVE
2456
2457 static int
2458 calc_section_size (MonoDynamicImage *assembly)
2459 {
2460         int nsections = 0;
2461
2462         /* alignment constraints */
2463         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
2464         g_assert ((assembly->code.index % 4) == 0);
2465         assembly->meta_size += 3;
2466         assembly->meta_size &= ~3;
2467         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
2468         g_assert ((assembly->resources.index % 4) == 0);
2469
2470         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
2471         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
2472         nsections++;
2473
2474         if (assembly->win32_res) {
2475                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
2476
2477                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
2478                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
2479                 nsections++;
2480         }
2481
2482         assembly->sections [MONO_SECTION_RELOC].size = 12;
2483         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
2484         nsections++;
2485
2486         return nsections;
2487 }
2488
2489 typedef struct {
2490         guint32 id;
2491         guint32 offset;
2492         GSList *children;
2493         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
2494 } ResTreeNode;
2495
2496 static int
2497 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
2498 {
2499         ResTreeNode *t1 = (ResTreeNode*)a;
2500         ResTreeNode *t2 = (ResTreeNode*)b;
2501
2502         return t1->id - t2->id;
2503 }
2504
2505 /*
2506  * resource_tree_create:
2507  *
2508  *  Organize the resources into a resource tree.
2509  */
2510 static ResTreeNode *
2511 resource_tree_create (MonoArray *win32_resources)
2512 {
2513         ResTreeNode *tree, *res_node, *type_node, *lang_node;
2514         GSList *l;
2515         int i;
2516
2517         tree = g_new0 (ResTreeNode, 1);
2518         
2519         for (i = 0; i < mono_array_length (win32_resources); ++i) {
2520                 MonoReflectionWin32Resource *win32_res =
2521                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
2522
2523                 /* Create node */
2524
2525                 /* FIXME: BUG: this stores managed references in unmanaged memory */
2526                 lang_node = g_new0 (ResTreeNode, 1);
2527                 lang_node->id = win32_res->lang_id;
2528                 lang_node->win32_res = win32_res;
2529
2530                 /* Create type node if neccesary */
2531                 type_node = NULL;
2532                 for (l = tree->children; l; l = l->next)
2533                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
2534                                 type_node = (ResTreeNode*)l->data;
2535                                 break;
2536                         }
2537
2538                 if (!type_node) {
2539                         type_node = g_new0 (ResTreeNode, 1);
2540                         type_node->id = win32_res->res_type;
2541
2542                         /* 
2543                          * The resource types have to be sorted otherwise
2544                          * Windows Explorer can't display the version information.
2545                          */
2546                         tree->children = g_slist_insert_sorted (tree->children, 
2547                                 type_node, resource_tree_compare_by_id);
2548                 }
2549
2550                 /* Create res node if neccesary */
2551                 res_node = NULL;
2552                 for (l = type_node->children; l; l = l->next)
2553                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
2554                                 res_node = (ResTreeNode*)l->data;
2555                                 break;
2556                         }
2557
2558                 if (!res_node) {
2559                         res_node = g_new0 (ResTreeNode, 1);
2560                         res_node->id = win32_res->res_id;
2561                         type_node->children = g_slist_append (type_node->children, res_node);
2562                 }
2563
2564                 res_node->children = g_slist_append (res_node->children, lang_node);
2565         }
2566
2567         return tree;
2568 }
2569
2570 /*
2571  * resource_tree_encode:
2572  * 
2573  *   Encode the resource tree into the format used in the PE file.
2574  */
2575 static void
2576 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
2577 {
2578         char *entries;
2579         MonoPEResourceDir dir;
2580         MonoPEResourceDirEntry dir_entry;
2581         MonoPEResourceDataEntry data_entry;
2582         GSList *l;
2583         guint32 res_id_entries;
2584
2585         /*
2586          * For the format of the resource directory, see the article
2587          * "An In-Depth Look into the Win32 Portable Executable File Format" by
2588          * Matt Pietrek
2589          */
2590
2591         memset (&dir, 0, sizeof (dir));
2592         memset (&dir_entry, 0, sizeof (dir_entry));
2593         memset (&data_entry, 0, sizeof (data_entry));
2594
2595         g_assert (sizeof (dir) == 16);
2596         g_assert (sizeof (dir_entry) == 8);
2597         g_assert (sizeof (data_entry) == 16);
2598
2599         node->offset = p - begin;
2600
2601         /* IMAGE_RESOURCE_DIRECTORY */
2602         res_id_entries = g_slist_length (node->children);
2603         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
2604
2605         memcpy (p, &dir, sizeof (dir));
2606         p += sizeof (dir);
2607
2608         /* Reserve space for entries */
2609         entries = p;
2610         p += sizeof (dir_entry) * res_id_entries;
2611
2612         /* Write children */
2613         for (l = node->children; l; l = l->next) {
2614                 ResTreeNode *child = (ResTreeNode*)l->data;
2615
2616                 if (child->win32_res) {
2617                         guint32 size;
2618
2619                         child->offset = p - begin;
2620
2621                         /* IMAGE_RESOURCE_DATA_ENTRY */
2622                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
2623                         size = mono_array_length (child->win32_res->res_data);
2624                         data_entry.rde_size = GUINT32_TO_LE (size);
2625
2626                         memcpy (p, &data_entry, sizeof (data_entry));
2627                         p += sizeof (data_entry);
2628
2629                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
2630                         p += size;
2631                 } else {
2632                         resource_tree_encode (child, begin, p, &p);
2633                 }
2634         }
2635
2636         /* IMAGE_RESOURCE_ENTRY */
2637         for (l = node->children; l; l = l->next) {
2638                 ResTreeNode *child = (ResTreeNode*)l->data;
2639
2640                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
2641                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
2642
2643                 memcpy (entries, &dir_entry, sizeof (dir_entry));
2644                 entries += sizeof (dir_entry);
2645         }
2646
2647         *endbuf = p;
2648 }
2649
2650 static void
2651 resource_tree_free (ResTreeNode * node)
2652 {
2653         GSList * list;
2654         for (list = node->children; list; list = list->next)
2655                 resource_tree_free ((ResTreeNode*)list->data);
2656         g_slist_free(node->children);
2657         g_free (node);
2658 }
2659
2660 static void
2661 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
2662 {
2663         char *buf;
2664         char *p;
2665         guint32 size, i;
2666         MonoReflectionWin32Resource *win32_res;
2667         ResTreeNode *tree;
2668
2669         if (!assemblyb->win32_resources)
2670                 return;
2671
2672         /*
2673          * Resources are stored in a three level tree inside the PE file.
2674          * - level one contains a node for each type of resource
2675          * - level two contains a node for each resource
2676          * - level three contains a node for each instance of a resource for a
2677          *   specific language.
2678          */
2679
2680         tree = resource_tree_create (assemblyb->win32_resources);
2681
2682         /* Estimate the size of the encoded tree */
2683         size = 0;
2684         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
2685                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
2686                 size += mono_array_length (win32_res->res_data);
2687         }
2688         /* Directory structure */
2689         size += mono_array_length (assemblyb->win32_resources) * 256;
2690         p = buf = (char *)g_malloc (size);
2691
2692         resource_tree_encode (tree, p, p, &p);
2693
2694         g_assert (p - buf <= size);
2695
2696         assembly->win32_res = (char *)g_malloc (p - buf);
2697         assembly->win32_res_size = p - buf;
2698         memcpy (assembly->win32_res, buf, p - buf);
2699
2700         g_free (buf);
2701         resource_tree_free (tree);
2702 }
2703
2704 static void
2705 fixup_resource_directory (char *res_section, char *p, guint32 rva)
2706 {
2707         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
2708         int i;
2709
2710         p += sizeof (MonoPEResourceDir);
2711         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
2712                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
2713                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
2714                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
2715                         fixup_resource_directory (res_section, child, rva);
2716                 } else {
2717                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
2718                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
2719                 }
2720
2721                 p += sizeof (MonoPEResourceDirEntry);
2722         }
2723 }
2724
2725 static void
2726 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
2727 {
2728         guint32 dummy;
2729         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
2730                 g_error ("WriteFile returned %d\n", GetLastError ());
2731 }
2732
2733 /*
2734  * mono_image_create_pefile:
2735  * @mb: a module builder object
2736  * 
2737  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
2738  * assembly->pefile where it can be easily retrieved later in chunks.
2739  */
2740 gboolean
2741 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
2742 {
2743         MonoMSDOSHeader *msdos;
2744         MonoDotNetHeader *header;
2745         MonoSectionTable *section;
2746         MonoCLIHeader *cli_header;
2747         guint32 size, image_size, virtual_base, text_offset;
2748         guint32 header_start, section_start, file_offset, virtual_offset;
2749         MonoDynamicImage *assembly;
2750         MonoReflectionAssemblyBuilder *assemblyb;
2751         MonoDynamicStream pefile_stream = {0};
2752         MonoDynamicStream *pefile = &pefile_stream;
2753         int i, nsections;
2754         guint32 *rva, value;
2755         guchar *p;
2756         static const unsigned char msheader[] = {
2757                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
2758                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2759                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2760                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
2761                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
2762                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
2763                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
2764                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2765         };
2766
2767         mono_error_init (error);
2768
2769         assemblyb = mb->assemblyb;
2770
2771         mono_reflection_dynimage_basic_init (assemblyb);
2772         assembly = mb->dynamic_image;
2773
2774         assembly->pe_kind = assemblyb->pe_kind;
2775         assembly->machine = assemblyb->machine;
2776         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
2777         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
2778         
2779         if (!mono_image_build_metadata (mb, error))
2780                 return FALSE;
2781         
2782
2783         if (mb->is_main && assemblyb->resources) {
2784                 int len = mono_array_length (assemblyb->resources);
2785                 for (i = 0; i < len; ++i) {
2786                         if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i), error))
2787                                 return FALSE;
2788                 }
2789         }
2790
2791         if (mb->resources) {
2792                 int len = mono_array_length (mb->resources);
2793                 for (i = 0; i < len; ++i) {
2794                         if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i), error))
2795                                 return FALSE;
2796                 }
2797         }
2798
2799         if (!build_compressed_metadata (assembly, error))
2800                 return FALSE;
2801
2802         if (mb->is_main)
2803                 assembly_add_win32_resources (assembly, assemblyb);
2804
2805         nsections = calc_section_size (assembly);
2806         
2807         /* The DOS header and stub */
2808         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
2809         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
2810
2811         /* the dotnet header */
2812         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
2813
2814         /* the section tables */
2815         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
2816
2817         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
2818         virtual_offset = VIRT_ALIGN;
2819         image_size = 0;
2820
2821         for (i = 0; i < MONO_SECTION_MAX; ++i) {
2822                 if (!assembly->sections [i].size)
2823                         continue;
2824                 /* align offsets */
2825                 file_offset += FILE_ALIGN - 1;
2826                 file_offset &= ~(FILE_ALIGN - 1);
2827                 virtual_offset += VIRT_ALIGN - 1;
2828                 virtual_offset &= ~(VIRT_ALIGN - 1);
2829
2830                 assembly->sections [i].offset = file_offset;
2831                 assembly->sections [i].rva = virtual_offset;
2832
2833                 file_offset += assembly->sections [i].size;
2834                 virtual_offset += assembly->sections [i].size;
2835                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
2836         }
2837
2838         file_offset += FILE_ALIGN - 1;
2839         file_offset &= ~(FILE_ALIGN - 1);
2840
2841         image_size += section_start + sizeof (MonoSectionTable) * nsections;
2842
2843         /* back-patch info */
2844         msdos = (MonoMSDOSHeader*)pefile->data;
2845         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
2846
2847         header = (MonoDotNetHeader*)(pefile->data + header_start);
2848         header->pesig [0] = 'P';
2849         header->pesig [1] = 'E';
2850         
2851         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
2852         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
2853         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
2854         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
2855         if (assemblyb->pekind == 1) {
2856                 /* it's a dll */
2857                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
2858         } else {
2859                 /* it's an exe */
2860                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
2861         }
2862
2863         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
2864
2865         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
2866         header->pe.pe_major = 6;
2867         header->pe.pe_minor = 0;
2868         size = assembly->sections [MONO_SECTION_TEXT].size;
2869         size += FILE_ALIGN - 1;
2870         size &= ~(FILE_ALIGN - 1);
2871         header->pe.pe_code_size = GUINT32_FROM_LE(size);
2872         size = assembly->sections [MONO_SECTION_RSRC].size;
2873         size += FILE_ALIGN - 1;
2874         size &= ~(FILE_ALIGN - 1);
2875         header->pe.pe_data_size = GUINT32_FROM_LE(size);
2876         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
2877         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
2878         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2879         /* pe_rva_entry_point always at the beginning of the text section */
2880         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
2881
2882         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
2883         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
2884         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
2885         header->nt.pe_os_major = GUINT16_FROM_LE (4);
2886         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
2887         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
2888         size = section_start;
2889         size += FILE_ALIGN - 1;
2890         size &= ~(FILE_ALIGN - 1);
2891         header->nt.pe_header_size = GUINT32_FROM_LE (size);
2892         size = image_size;
2893         size += VIRT_ALIGN - 1;
2894         size &= ~(VIRT_ALIGN - 1);
2895         header->nt.pe_image_size = GUINT32_FROM_LE (size);
2896
2897         /*
2898         // Translate the PEFileKind value to the value expected by the Windows loader
2899         */
2900         {
2901                 short kind;
2902
2903                 /*
2904                 // PEFileKinds.Dll == 1
2905                 // PEFileKinds.ConsoleApplication == 2
2906                 // PEFileKinds.WindowApplication == 3
2907                 //
2908                 // need to get:
2909                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
2910                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
2911                 */
2912                 if (assemblyb->pekind == 3)
2913                         kind = 2;
2914                 else
2915                         kind = 3;
2916                 
2917                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
2918         }    
2919         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
2920         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
2921         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
2922         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
2923         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
2924         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
2925
2926         /* fill data directory entries */
2927
2928         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
2929         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2930
2931         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
2932         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
2933
2934         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
2935         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
2936         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
2937         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2938         /* patch entrypoint name */
2939         if (assemblyb->pekind == 1)
2940                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
2941         else
2942                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
2943         /* patch imported function RVA name */
2944         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
2945         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
2946
2947         /* the import table */
2948         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
2949         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
2950         /* patch imported dll RVA name and other entries in the dir */
2951         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
2952         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
2953         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
2954         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2955         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
2956         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
2957
2958         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
2959         value = (assembly->text_rva + assembly->imp_names_offset);
2960         *p++ = (value) & 0xff;
2961         *p++ = (value >> 8) & (0xff);
2962         *p++ = (value >> 16) & (0xff);
2963         *p++ = (value >> 24) & (0xff);
2964
2965         /* the CLI header info */
2966         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
2967         cli_header->ch_size = GUINT32_FROM_LE (72);
2968         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
2969         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
2970         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
2971         if (assemblyb->entry_point) {
2972                 guint32 table_idx = 0;
2973                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
2974                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
2975                         table_idx = methodb->table_idx;
2976                 } else {
2977                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
2978                 }
2979                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
2980         } else {
2981                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
2982         }
2983         /* The embedded managed resources */
2984         text_offset = assembly->text_rva + assembly->code.index;
2985         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
2986         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
2987         text_offset += assembly->resources.index;
2988         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
2989         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
2990         text_offset += assembly->meta_size;
2991         if (assembly->strong_name_size) {
2992                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
2993                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
2994                 text_offset += assembly->strong_name_size;
2995         }
2996
2997         /* write the section tables and section content */
2998         section = (MonoSectionTable*)(pefile->data + section_start);
2999         for (i = 0; i < MONO_SECTION_MAX; ++i) {
3000                 static const char section_names [][7] = {
3001                         ".text", ".rsrc", ".reloc"
3002                 };
3003                 if (!assembly->sections [i].size)
3004                         continue;
3005                 strcpy (section->st_name, section_names [i]);
3006                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
3007                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
3008                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
3009                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
3010                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
3011                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
3012                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
3013                 section ++;
3014         }
3015         
3016         checked_write_file (file, pefile->data, pefile->index);
3017         
3018         mono_dynamic_stream_reset (pefile);
3019         
3020         for (i = 0; i < MONO_SECTION_MAX; ++i) {
3021                 if (!assembly->sections [i].size)
3022                         continue;
3023                 
3024                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
3025                         g_error ("SetFilePointer returned %d\n", GetLastError ());
3026                 
3027                 switch (i) {
3028                 case MONO_SECTION_TEXT:
3029                         /* patch entry point */
3030                         p = (guchar*)(assembly->code.data + 2);
3031                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
3032                         *p++ = (value) & 0xff;
3033                         *p++ = (value >> 8) & 0xff;
3034                         *p++ = (value >> 16) & 0xff;
3035                         *p++ = (value >> 24) & 0xff;
3036                 
3037                         checked_write_file (file, assembly->code.data, assembly->code.index);
3038                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
3039                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
3040                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
3041                                 
3042
3043                         g_free (assembly->image.raw_metadata);
3044                         break;
3045                 case MONO_SECTION_RELOC: {
3046                         struct {
3047                                 guint32 page_rva;
3048                                 guint32 block_size;
3049                                 guint16 type_and_offset;
3050                                 guint16 term;
3051                         } reloc;
3052                         
3053                         g_assert (sizeof (reloc) == 12);
3054                         
3055                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
3056                         reloc.block_size = GUINT32_FROM_LE (12);
3057                         
3058                         /* 
3059                          * the entrypoint is always at the start of the text section 
3060                          * 3 is IMAGE_REL_BASED_HIGHLOW
3061                          * 2 is patch_size_rva - text_rva
3062                          */
3063                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
3064                         reloc.term = 0;
3065                         
3066                         checked_write_file (file, &reloc, sizeof (reloc));
3067                         
3068                         break;
3069                 }
3070                 case MONO_SECTION_RSRC:
3071                         if (assembly->win32_res) {
3072
3073                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
3074                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
3075                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
3076                         }
3077                         break;
3078                 default:
3079                         g_assert_not_reached ();
3080                 }
3081         }
3082         
3083         /* check that the file is properly padded */
3084         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
3085                 g_error ("SetFilePointer returned %d\n", GetLastError ());
3086         if (! SetEndOfFile (file))
3087                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
3088         
3089         mono_dynamic_stream_reset (&assembly->code);
3090         mono_dynamic_stream_reset (&assembly->us);
3091         mono_dynamic_stream_reset (&assembly->blob);
3092         mono_dynamic_stream_reset (&assembly->guid);
3093         mono_dynamic_stream_reset (&assembly->sheap);
3094
3095         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
3096         g_hash_table_destroy (assembly->blob_cache);
3097         assembly->blob_cache = NULL;
3098
3099         return TRUE;
3100 }
3101
3102 #else /* DISABLE_REFLECTION_EMIT_SAVE */
3103
3104 gboolean
3105 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
3106 {
3107         g_assert_not_reached ();
3108 }
3109
3110 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
3111