Convert MonoClassExt to class properties (#4022)
[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         GList *nested_classes = mono_class_get_nested_classes_property (klass);
1221         GList *tmp;
1222         for (tmp = nested_classes; tmp; tmp = tmp->next)
1223                 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
1224
1225         return res;
1226 }
1227
1228 static void
1229 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
1230                               guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
1231                               MonoError *error)
1232 {
1233         MonoClass *klass;
1234         guint32 idx, i;
1235
1236         mono_error_init (error);
1237
1238         MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
1239         return_if_nok (error);
1240
1241         klass = mono_class_from_mono_type (t);
1242
1243         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
1244
1245         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
1246                                                                                                    parent_index, assembly);
1247
1248         /* 
1249          * Emit nested types
1250          * We need to do this ourselves since klass->nested_classes is not set up.
1251          */
1252         if (tb->subtypes) {
1253                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1254                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
1255                         return_if_nok (error);
1256                 }
1257         }
1258 }
1259
1260 static void
1261 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
1262         guint32 module_index, MonoDynamicImage *assembly)
1263 {
1264         MonoImage *image = module->image;
1265         MonoTableInfo  *t;
1266         guint32 i;
1267
1268         t = &image->tables [MONO_TABLE_TYPEDEF];
1269
1270         for (i = 0; i < t->rows; ++i) {
1271                 MonoError error;
1272                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
1273                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1274
1275                 if (mono_class_is_public (klass))
1276                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
1277         }
1278 }
1279
1280 static void
1281 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
1282 {
1283         MonoDynamicTable *table;
1284         guint32 *values;
1285         guint32 scope, scope_idx, impl, current_idx;
1286         gboolean forwarder = TRUE;
1287         gpointer iter = NULL;
1288         MonoClass *nested;
1289
1290         if (klass->nested_in) {
1291                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
1292                 forwarder = FALSE;
1293         } else {
1294                 scope = mono_reflection_resolution_scope_from_image (assembly, klass->image);
1295                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
1296                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
1297                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
1298         }
1299
1300         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
1301
1302         table->rows++;
1303         alloc_table (table, table->rows);
1304         current_idx = table->next_idx;
1305         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
1306
1307         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
1308         values [MONO_EXP_TYPE_TYPEDEF] = 0;
1309         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
1310         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1311         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1312
1313         table->next_idx++;
1314
1315         while ((nested = mono_class_get_nested_types (klass, &iter)))
1316                 add_exported_type (assemblyb, assembly, nested, current_idx);
1317 }
1318
1319 static void
1320 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
1321 {
1322         MonoError error;
1323         MonoClass *klass;
1324         int i;
1325
1326         if (!assemblyb->type_forwarders)
1327                 return;
1328
1329         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
1330                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
1331                 MonoType *type;
1332                 if (!t)
1333                         continue;
1334
1335                 type = mono_reflection_type_get_handle (t, &error);
1336                 mono_error_assert_ok (&error);
1337                 g_assert (type);
1338
1339                 klass = mono_class_from_mono_type (type);
1340
1341                 add_exported_type (assemblyb, assembly, klass, 0);
1342         }
1343 }
1344
1345 #define align_pointer(base,p)\
1346         do {\
1347                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1348                 if (__diff & 3)\
1349                         (p) += 4 - (__diff & 3);\
1350         } while (0)
1351
1352 static int
1353 compare_constants (const void *a, const void *b)
1354 {
1355         const guint32 *a_values = (const guint32 *)a;
1356         const guint32 *b_values = (const guint32 *)b;
1357         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
1358 }
1359
1360 static int
1361 compare_semantics (const void *a, const void *b)
1362 {
1363         const guint32 *a_values = (const guint32 *)a;
1364         const guint32 *b_values = (const guint32 *)b;
1365         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
1366         if (assoc)
1367                 return assoc;
1368         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
1369 }
1370
1371 static int
1372 compare_custom_attrs (const void *a, const void *b)
1373 {
1374         const guint32 *a_values = (const guint32 *)a;
1375         const guint32 *b_values = (const guint32 *)b;
1376
1377         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
1378 }
1379
1380 static int
1381 compare_field_marshal (const void *a, const void *b)
1382 {
1383         const guint32 *a_values = (const guint32 *)a;
1384         const guint32 *b_values = (const guint32 *)b;
1385
1386         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
1387 }
1388
1389 static int
1390 compare_nested (const void *a, const void *b)
1391 {
1392         const guint32 *a_values = (const guint32 *)a;
1393         const guint32 *b_values = (const guint32 *)b;
1394
1395         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
1396 }
1397
1398 static int
1399 compare_genericparam (const void *a, const void *b)
1400 {
1401         MonoError error;
1402         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
1403         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
1404
1405         if ((*b_entry)->owner == (*a_entry)->owner) {
1406                 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
1407                 mono_error_assert_ok (&error);
1408                 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
1409                 mono_error_assert_ok (&error);
1410                 return 
1411                         mono_type_get_generic_param_num (a_type) -
1412                         mono_type_get_generic_param_num (b_type);
1413         } else
1414                 return (*a_entry)->owner - (*b_entry)->owner;
1415 }
1416
1417 static int
1418 compare_declsecurity_attrs (const void *a, const void *b)
1419 {
1420         const guint32 *a_values = (const guint32 *)a;
1421         const guint32 *b_values = (const guint32 *)b;
1422
1423         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
1424 }
1425
1426 static int
1427 compare_interface_impl (const void *a, const void *b)
1428 {
1429         const guint32 *a_values = (const guint32 *)a;
1430         const guint32 *b_values = (const guint32 *)b;
1431
1432         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
1433         if (klass)
1434                 return klass;
1435
1436         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
1437 }
1438
1439 struct StreamDesc {
1440         const char *name;
1441         MonoDynamicStream *stream;
1442 };
1443
1444 /*
1445  * build_compressed_metadata() fills in the blob of data that represents the 
1446  * raw metadata as it will be saved in the PE file. The five streams are output 
1447  * and the metadata tables are comnpressed from the guint32 array representation, 
1448  * to the compressed on-disk format.
1449  */
1450 static gboolean
1451 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
1452 {
1453         MonoDynamicTable *table;
1454         int i;
1455         guint64 valid_mask = 0;
1456         guint64 sorted_mask;
1457         guint32 heapt_size = 0;
1458         guint32 meta_size = 256; /* allow for header and other stuff */
1459         guint32 table_offset;
1460         guint32 ntables = 0;
1461         guint64 *int64val;
1462         guint32 *int32val;
1463         guint16 *int16val;
1464         MonoImage *meta;
1465         unsigned char *p;
1466         struct StreamDesc stream_desc [5];
1467
1468         mono_error_init (error);
1469
1470         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
1471         for (i = 0; i < assembly->gen_params->len; i++) {
1472                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
1473                 if (!write_generic_param_entry (assembly, entry, error))
1474                         return FALSE;
1475         }
1476
1477         stream_desc [0].name  = "#~";
1478         stream_desc [0].stream = &assembly->tstream;
1479         stream_desc [1].name  = "#Strings";
1480         stream_desc [1].stream = &assembly->sheap;
1481         stream_desc [2].name  = "#US";
1482         stream_desc [2].stream = &assembly->us;
1483         stream_desc [3].name  = "#Blob";
1484         stream_desc [3].stream = &assembly->blob;
1485         stream_desc [4].name  = "#GUID";
1486         stream_desc [4].stream = &assembly->guid;
1487         
1488         /* tables that are sorted */
1489         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
1490                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
1491                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
1492                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
1493                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
1494                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
1495                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
1496         
1497         /* Compute table sizes */
1498         /* the MonoImage has already been created in mono_reflection_dynimage_basic_init() */
1499         meta = &assembly->image;
1500
1501         /* sizes should be multiple of 4 */
1502         mono_dynstream_data_align (&assembly->blob);
1503         mono_dynstream_data_align (&assembly->guid);
1504         mono_dynstream_data_align (&assembly->sheap);
1505         mono_dynstream_data_align (&assembly->us);
1506
1507         /* Setup the info used by compute_sizes () */
1508         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
1509         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
1510         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
1511
1512         meta_size += assembly->blob.index;
1513         meta_size += assembly->guid.index;
1514         meta_size += assembly->sheap.index;
1515         meta_size += assembly->us.index;
1516
1517         for (i=0; i < MONO_TABLE_NUM; ++i)
1518                 meta->tables [i].rows = assembly->tables [i].rows;
1519         
1520         for (i = 0; i < MONO_TABLE_NUM; i++){
1521                 if (meta->tables [i].rows == 0)
1522                         continue;
1523                 valid_mask |= (guint64)1 << i;
1524                 ntables ++;
1525                 meta->tables [i].row_size = mono_metadata_compute_size (
1526                         meta, i, &meta->tables [i].size_bitfield);
1527                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
1528         }
1529         heapt_size += 24; /* #~ header size */
1530         heapt_size += ntables * 4;
1531         /* make multiple of 4 */
1532         heapt_size += 3;
1533         heapt_size &= ~3;
1534         meta_size += heapt_size;
1535         meta->raw_metadata = (char *)g_malloc0 (meta_size);
1536         p = (unsigned char*)meta->raw_metadata;
1537         /* the metadata signature */
1538         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
1539         /* version numbers and 4 bytes reserved */
1540         int16val = (guint16*)p;
1541         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
1542         *int16val = GUINT16_TO_LE (meta->md_version_minor);
1543         p += 8;
1544         /* version string */
1545         int32val = (guint32*)p;
1546         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
1547         p += 4;
1548         memcpy (p, meta->version, strlen (meta->version));
1549         p += GUINT32_FROM_LE (*int32val);
1550         align_pointer (meta->raw_metadata, p);
1551         int16val = (guint16*)p;
1552         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
1553         *int16val = GUINT16_TO_LE (5); /* number of streams */
1554         p += 4;
1555
1556         /*
1557          * write the stream info.
1558          */
1559         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
1560         table_offset += 3; table_offset &= ~3;
1561
1562         assembly->tstream.index = heapt_size;
1563         for (i = 0; i < 5; ++i) {
1564                 int32val = (guint32*)p;
1565                 stream_desc [i].stream->offset = table_offset;
1566                 *int32val++ = GUINT32_TO_LE (table_offset);
1567                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
1568                 table_offset += GUINT32_FROM_LE (*int32val);
1569                 table_offset += 3; table_offset &= ~3;
1570                 p += 8;
1571                 strcpy ((char*)p, stream_desc [i].name);
1572                 p += strlen (stream_desc [i].name) + 1;
1573                 align_pointer (meta->raw_metadata, p);
1574         }
1575         /* 
1576          * now copy the data, the table stream header and contents goes first.
1577          */
1578         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
1579         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
1580         int32val = (guint32*)p;
1581         *int32val = GUINT32_TO_LE (0); /* reserved */
1582         p += 4;
1583
1584         *p++ = 2; /* version */
1585         *p++ = 0;
1586
1587         if (meta->idx_string_wide)
1588                 *p |= 0x01;
1589         if (meta->idx_guid_wide)
1590                 *p |= 0x02;
1591         if (meta->idx_blob_wide)
1592                 *p |= 0x04;
1593         ++p;
1594         *p++ = 1; /* reserved */
1595         int64val = (guint64*)p;
1596         *int64val++ = GUINT64_TO_LE (valid_mask);
1597         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
1598         p += 16;
1599         int32val = (guint32*)p;
1600         for (i = 0; i < MONO_TABLE_NUM; i++){
1601                 if (meta->tables [i].rows == 0)
1602                         continue;
1603                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
1604         }
1605         p = (unsigned char*)int32val;
1606
1607         /* sort the tables that still need sorting */
1608         table = &assembly->tables [MONO_TABLE_CONSTANT];
1609         if (table->rows)
1610                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
1611         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1612         if (table->rows)
1613                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
1614         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1615         if (table->rows)
1616                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
1617         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1618         if (table->rows)
1619                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
1620         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1621         if (table->rows)
1622                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
1623         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
1624         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1625         if (table->rows)
1626                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
1627         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1628         if (table->rows)
1629                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
1630
1631         /* compress the tables */
1632         for (i = 0; i < MONO_TABLE_NUM; i++){
1633                 int row, col;
1634                 guint32 *values;
1635                 guint32 bitfield = meta->tables [i].size_bitfield;
1636                 if (!meta->tables [i].rows)
1637                         continue;
1638                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
1639                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
1640                 meta->tables [i].base = (char*)p;
1641                 for (row = 1; row <= meta->tables [i].rows; ++row) {
1642                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
1643                         for (col = 0; col < assembly->tables [i].columns; ++col) {
1644                                 switch (mono_metadata_table_size (bitfield, col)) {
1645                                 case 1:
1646                                         *p++ = values [col];
1647                                         break;
1648                                 case 2:
1649                                         *p++ = values [col] & 0xff;
1650                                         *p++ = (values [col] >> 8) & 0xff;
1651                                         break;
1652                                 case 4:
1653                                         *p++ = values [col] & 0xff;
1654                                         *p++ = (values [col] >> 8) & 0xff;
1655                                         *p++ = (values [col] >> 16) & 0xff;
1656                                         *p++ = (values [col] >> 24) & 0xff;
1657                                         break;
1658                                 default:
1659                                         g_assert_not_reached ();
1660                                 }
1661                         }
1662                 }
1663                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
1664         }
1665         
1666         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
1667         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
1668         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
1669         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
1670         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
1671
1672         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
1673
1674         return TRUE;
1675 }
1676
1677 /*
1678  * Some tables in metadata need to be sorted according to some criteria, but
1679  * when methods and fields are first created with reflection, they may be assigned a token
1680  * that doesn't correspond to the final token they will get assigned after the sorting.
1681  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
1682  * with the reflection objects that represent them. Once all the tables are set up, the 
1683  * reflection objects will contains the correct table index. fixup_method() will fixup the
1684  * tokens for the method with ILGenerator @ilgen.
1685  */
1686 static void
1687 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
1688 {
1689         guint32 code_idx = GPOINTER_TO_UINT (value);
1690         MonoReflectionILTokenInfo *iltoken;
1691         MonoReflectionTypeBuilder *tb;
1692         MonoReflectionArrayMethod *am;
1693         guint32 i, idx = 0;
1694         unsigned char *target;
1695
1696         for (i = 0; i < ilgen->num_token_fixups; ++i) {
1697                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
1698                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
1699                 switch (target [3]) {
1700                 case MONO_TABLE_FIELD:
1701                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
1702                                 g_assert_not_reached ();
1703                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
1704                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
1705                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
1706                         } else {
1707                                 g_assert_not_reached ();
1708                         }
1709                         break;
1710                 case MONO_TABLE_METHOD:
1711                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
1712                                 g_assert_not_reached ();
1713                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
1714                                 g_assert_not_reached ();
1715                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
1716                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
1717                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
1718                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
1719                         } else {
1720                                 g_assert_not_reached ();
1721                         }
1722                         break;
1723                 case MONO_TABLE_TYPEDEF:
1724                         if (!strcmp (iltoken->member->vtable->klass->name, "TypeBuilder")) {
1725                                 g_assert_not_reached ();
1726                         } else if (!strcmp (iltoken->member->vtable->klass->name, "RuntimeType")) {
1727                                 MonoClass *k = mono_class_from_mono_type (((MonoReflectionType*)iltoken->member)->type);
1728                                 MonoObject *obj = mono_class_get_ref_info (k);
1729                                 g_assert (obj);
1730                                 g_assert (!strcmp (obj->vtable->klass->name, "TypeBuilder"));
1731                                 tb = (MonoReflectionTypeBuilder*)obj;
1732                                 idx = tb->table_idx;
1733                         } else {
1734                                 g_assert_not_reached ();
1735                         }
1736                         break;
1737                 case MONO_TABLE_MEMBERREF:
1738                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
1739                                 am = (MonoReflectionArrayMethod*)iltoken->member;
1740                                 idx = am->table_idx;
1741                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
1742                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
1743                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
1744                                 g_assert (mono_class_is_ginst (m->klass) || mono_class_is_gtd (m->klass));
1745                                 continue;
1746                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
1747                                 g_assert_not_reached ();
1748                                 continue;
1749                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
1750                                 continue;
1751                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
1752                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
1753                                 g_assert_not_reached ();
1754                                 continue;
1755                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
1756                                 g_assert_not_reached ();
1757                                 continue;
1758                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
1759                                 g_assert_not_reached ();
1760                                 continue;
1761                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
1762                                 g_assert_not_reached ();
1763                                 continue;
1764                         } else {
1765                                 g_assert_not_reached ();
1766                         }
1767                         break;
1768                 case MONO_TABLE_METHODSPEC:
1769                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
1770                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
1771                                 g_assert (mono_method_signature (m)->generic_param_count);
1772                                 continue;
1773                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
1774                                 g_assert_not_reached ();
1775                                 continue;
1776                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
1777                                 g_assert_not_reached ();
1778                                 continue;
1779                         } else {
1780                                 g_assert_not_reached ();
1781                         }
1782                         break;
1783                 case MONO_TABLE_TYPESPEC:
1784                         if (!strcmp (iltoken->member->vtable->klass->name, "RuntimeType")) {
1785                                 continue;
1786                         } else {
1787                                 g_assert_not_reached ();
1788                         }
1789                         break;
1790                 default:
1791                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
1792                 }
1793                 target [0] = idx & 0xff;
1794                 target [1] = (idx >> 8) & 0xff;
1795                 target [2] = (idx >> 16) & 0xff;
1796         }
1797 }
1798
1799 /*
1800  * fixup_cattrs:
1801  *
1802  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
1803  * value is not known when the table is emitted.
1804  */
1805 static void
1806 fixup_cattrs (MonoDynamicImage *assembly)
1807 {
1808         MonoDynamicTable *table;
1809         guint32 *values;
1810         guint32 type, i, idx, token;
1811         MonoObject *ctor;
1812
1813         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1814
1815         for (i = 0; i < table->rows; ++i) {
1816                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
1817
1818                 type = values [MONO_CUSTOM_ATTR_TYPE];
1819                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
1820                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
1821                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
1822                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
1823                         g_assert (ctor);
1824
1825                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
1826                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
1827                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
1828                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1829                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
1830                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
1831                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
1832                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1833                         }
1834                 }
1835         }
1836 }
1837
1838 static gboolean
1839 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation, MonoError *error)
1840 {
1841         MonoDynamicTable *table;
1842         guint32 *values;
1843
1844         mono_error_init (error);
1845
1846         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
1847         table->rows++;
1848         alloc_table (table, table->rows);
1849         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
1850         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
1851         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
1852         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name, error);
1853         return_val_if_nok (error, FALSE);
1854         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
1855         table->next_idx++;
1856         return TRUE;
1857 }
1858
1859 static gboolean
1860 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, MonoError *error)
1861 {
1862         MonoDynamicTable *table;
1863         guint32 *values;
1864         char blob_size [6];
1865         guchar hash [20];
1866         char *b = blob_size;
1867         char *name, *sname;
1868         guint32 idx, offset;
1869
1870         mono_error_init (error);
1871
1872         if (rsrc->filename) {
1873                 name = mono_string_to_utf8_checked (rsrc->filename, error);
1874                 return_val_if_nok (error, FALSE);
1875                 sname = g_path_get_basename (name);
1876         
1877                 table = &assembly->tables [MONO_TABLE_FILE];
1878                 table->rows++;
1879                 alloc_table (table, table->rows);
1880                 values = table->values + table->next_idx * MONO_FILE_SIZE;
1881                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
1882                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
1883                 g_free (sname);
1884
1885                 mono_sha1_get_digest_from_file (name, hash);
1886                 mono_metadata_encode_value (20, b, &b);
1887                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1888                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
1889                 g_free (name);
1890                 idx = table->next_idx++;
1891                 rsrc->offset = 0;
1892                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
1893         } else {
1894                 char sizebuf [4];
1895                 char *data;
1896                 guint len;
1897                 if (rsrc->data) {
1898                         data = mono_array_addr (rsrc->data, char, 0);
1899                         len = mono_array_length (rsrc->data);
1900                 } else {
1901                         data = NULL;
1902                         len = 0;
1903                 }
1904                 offset = len;
1905                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
1906                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
1907                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
1908                 mono_image_add_stream_data (&assembly->resources, data, len);
1909
1910                 if (!mb->is_main)
1911                         /* 
1912                          * The entry should be emitted into the MANIFESTRESOURCE table of 
1913                          * the main module, but that needs to reference the FILE table
1914                          * which isn't emitted yet.
1915                          */
1916                         return TRUE;
1917                 else
1918                         idx = 0;
1919         }
1920
1921         return assembly_add_resource_manifest (mb, assembly, rsrc, idx, error);
1922 }
1923
1924 static gboolean
1925 set_version_from_string (MonoString *version, guint32 *values, MonoError *error)
1926 {
1927         gchar *ver, *p, *str;
1928         guint32 i;
1929         
1930         mono_error_init (error);
1931
1932         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
1933         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
1934         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
1935         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
1936         if (!version)
1937                 return TRUE;
1938         ver = str = mono_string_to_utf8_checked (version, error);
1939         return_val_if_nok (error, FALSE);
1940         for (i = 0; i < 4; ++i) {
1941                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
1942                 switch (*p) {
1943                 case '.':
1944                         p++;
1945                         break;
1946                 case '*':
1947                         /* handle Revision and Build */
1948                         p++;
1949                         break;
1950                 }
1951                 ver = p;
1952         }
1953         g_free (str);
1954         return TRUE;
1955 }
1956
1957 static guint32
1958 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
1959         gsize len;
1960         guint32 token = 0;
1961         char blob_size [6];
1962         char *b = blob_size;
1963
1964         if (!pkey)
1965                 return token;
1966
1967         len = mono_array_length (pkey);
1968         mono_metadata_encode_value (len, b, &b);
1969         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
1970         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
1971
1972         assembly->public_key = (guint8 *)g_malloc (len);
1973         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
1974         assembly->public_key_len = len;
1975
1976         /* Special case: check for ECMA key (16 bytes) */
1977         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
1978                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
1979                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
1980         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
1981                 /* minimum key size (in 2.0) is 384 bits */
1982                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
1983         } else {
1984                 /* FIXME - verifier */
1985                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
1986                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
1987         }
1988         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
1989
1990         return token;
1991 }
1992
1993 static gboolean
1994 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
1995 {
1996         MonoDynamicTable *table;
1997         MonoDynamicImage *assembly;
1998         MonoReflectionAssemblyBuilder *assemblyb;
1999         MonoDomain *domain;
2000         guint32 *values;
2001         int i;
2002         guint32 module_index;
2003
2004         mono_error_init (error);
2005
2006         assemblyb = moduleb->assemblyb;
2007         assembly = moduleb->dynamic_image;
2008         domain = mono_object_domain (assemblyb);
2009
2010         /* Emit ASSEMBLY table */
2011         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
2012         alloc_table (table, 1);
2013         values = table->values + MONO_ASSEMBLY_SIZE;
2014         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
2015         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name, error);
2016         return_val_if_nok (error, FALSE);
2017         if (assemblyb->culture) {
2018                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture, error);
2019                 return_val_if_nok (error, FALSE);
2020         } else {
2021                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
2022         }
2023         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
2024         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
2025         if (!set_version_from_string (assemblyb->version, values, error))
2026                 return FALSE;
2027
2028         /* Emit FILE + EXPORTED_TYPE table */
2029         module_index = 0;
2030         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
2031                 int j;
2032                 MonoReflectionModuleBuilder *file_module = 
2033                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
2034                 if (file_module != moduleb) {
2035                         if (!mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly, error))
2036                                 return FALSE;
2037                         module_index ++;
2038                         if (file_module->types) {
2039                                 for (j = 0; j < file_module->num_types; ++j) {
2040                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
2041                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
2042                                         return_val_if_nok (error, FALSE);
2043                                 }
2044                         }
2045                 }
2046         }
2047         if (assemblyb->loaded_modules) {
2048                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
2049                         MonoReflectionModule *file_module = 
2050                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
2051                         if (!mono_image_fill_file_table (domain, file_module, assembly, error))
2052                                 return FALSE;
2053                         module_index ++;
2054                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
2055                 }
2056         }
2057         if (assemblyb->type_forwarders)
2058                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
2059
2060         /* Emit MANIFESTRESOURCE table */
2061         module_index = 0;
2062         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
2063                 int j;
2064                 MonoReflectionModuleBuilder *file_module = 
2065                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
2066                 /* The table for the main module is emitted later */
2067                 if (file_module != moduleb) {
2068                         module_index ++;
2069                         if (file_module->resources) {
2070                                 int len = mono_array_length (file_module->resources);
2071                                 for (j = 0; j < len; ++j) {
2072                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
2073                                         if (!assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS), error))
2074                                                 return FALSE;
2075                                 }
2076                         }
2077                 }
2078         }
2079         return TRUE;
2080 }
2081
2082 #ifndef DISABLE_REFLECTION_EMIT_SAVE
2083
2084 /*
2085  * Insert into the metadata tables all the info about the TypeBuilder tb.
2086  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2087  */
2088 static gboolean
2089 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
2090 {
2091         MonoDynamicTable *table;
2092         guint *values;
2093         int i, is_object = 0, is_system = 0;
2094         char *n;
2095
2096         mono_error_init (error);
2097
2098         table = &assembly->tables [MONO_TABLE_TYPEDEF];
2099         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2100         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2101         n = mono_string_to_utf8_checked (tb->name, error);
2102         return_val_if_nok (error, FALSE);
2103         if (strcmp (n, "Object") == 0)
2104                 is_object++;
2105         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2106         g_free (n);
2107         n = mono_string_to_utf8_checked (tb->nspace, error);
2108         return_val_if_nok (error, FALSE);
2109         if (strcmp (n, "System") == 0)
2110                 is_system++;
2111         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2112         g_free (n);
2113         if (tb->parent && !(is_system && is_object) && 
2114                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2115                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
2116                 return_val_if_nok (error, FALSE);
2117                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
2118         } else {
2119                 values [MONO_TYPEDEF_EXTENDS] = 0;
2120         }
2121         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2122         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2123
2124         /*
2125          * if we have explicitlayout or sequentiallayouts, output data in the
2126          * ClassLayout table.
2127          */
2128         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2129                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
2130                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2131                 table->rows++;
2132                 alloc_table (table, table->rows);
2133                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2134                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2135                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2136                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2137         }
2138
2139         /* handle interfaces */
2140         if (tb->interfaces) {
2141                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2142                 i = table->rows;
2143                 table->rows += mono_array_length (tb->interfaces);
2144                 alloc_table (table, table->rows);
2145                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2146                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2147                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2148                         MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
2149                         return_val_if_nok (error, FALSE);
2150                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2151                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
2152                         values += MONO_INTERFACEIMPL_SIZE;
2153                 }
2154         }
2155
2156         /* handle fields */
2157         if (tb->fields) {
2158                 table = &assembly->tables [MONO_TABLE_FIELD];
2159                 table->rows += tb->num_fields;
2160                 alloc_table (table, table->rows);
2161                 for (i = 0; i < tb->num_fields; ++i) {
2162                         mono_image_get_field_info (
2163                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
2164                         return_val_if_nok (error, FALSE);
2165                 }
2166         }
2167
2168         /* handle constructors */
2169         if (tb->ctors) {
2170                 table = &assembly->tables [MONO_TABLE_METHOD];
2171                 table->rows += mono_array_length (tb->ctors);
2172                 alloc_table (table, table->rows);
2173                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2174                         if (!mono_image_get_ctor_info (domain,
2175                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
2176                                                        assembly, error))
2177                                 return FALSE;
2178                 }
2179         }
2180
2181         /* handle methods */
2182         if (tb->methods) {
2183                 table = &assembly->tables [MONO_TABLE_METHOD];
2184                 table->rows += tb->num_methods;
2185                 alloc_table (table, table->rows);
2186                 for (i = 0; i < tb->num_methods; ++i) {
2187                         if (!mono_image_get_method_info (
2188                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
2189                                 return FALSE;
2190                 }
2191         }
2192
2193         /* Do the same with properties etc.. */
2194         if (tb->events && mono_array_length (tb->events)) {
2195                 table = &assembly->tables [MONO_TABLE_EVENT];
2196                 table->rows += mono_array_length (tb->events);
2197                 alloc_table (table, table->rows);
2198                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2199                 table->rows ++;
2200                 alloc_table (table, table->rows);
2201                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2202                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2203                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2204                 for (i = 0; i < mono_array_length (tb->events); ++i) {
2205                         mono_image_get_event_info (
2206                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
2207                         return_val_if_nok (error, FALSE);
2208                 }
2209         }
2210         if (tb->properties && mono_array_length (tb->properties)) {
2211                 table = &assembly->tables [MONO_TABLE_PROPERTY];
2212                 table->rows += mono_array_length (tb->properties);
2213                 alloc_table (table, table->rows);
2214                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2215                 table->rows ++;
2216                 alloc_table (table, table->rows);
2217                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2218                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2219                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2220                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2221                         mono_image_get_property_info (
2222                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
2223                         return_val_if_nok (error, FALSE);
2224                 }
2225         }
2226
2227         /* handle generic parameters */
2228         if (tb->generic_params) {
2229                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2230                 table->rows += mono_array_length (tb->generic_params);
2231                 alloc_table (table, table->rows);
2232                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2233                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2234
2235                         mono_image_get_generic_param_info (
2236                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2237                 }
2238         }
2239
2240         mono_image_add_decl_security (assembly, 
2241                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2242
2243         if (tb->subtypes) {
2244                 MonoDynamicTable *ntable;
2245                 
2246                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2247                 ntable->rows += mono_array_length (tb->subtypes);
2248                 alloc_table (ntable, ntable->rows);
2249                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2250
2251                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2252                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2253
2254                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2255                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2256                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2257                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2258                                 mono_string_to_utf8 (tb->name), tb->table_idx,
2259                                 ntable->next_idx, ntable->rows);*/
2260                         values += MONO_NESTED_CLASS_SIZE;
2261                         ntable->next_idx++;
2262                 }
2263         }
2264
2265         return TRUE;
2266 }
2267
2268
2269 /*
2270  * mono_image_build_metadata() will fill the info in all the needed metadata tables
2271  * for the modulebuilder @moduleb.
2272  * At the end of the process, method and field tokens are fixed up and the 
2273  * on-disk compressed metadata representation is created.
2274  * Return TRUE on success, or FALSE on failure and sets @error
2275  */
2276 gboolean
2277 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
2278 {
2279         MonoDynamicTable *table;
2280         MonoDynamicImage *assembly;
2281         MonoReflectionAssemblyBuilder *assemblyb;
2282         MonoDomain *domain;
2283         MonoPtrArray types;
2284         guint32 *values;
2285         int i, j;
2286
2287         mono_error_init (error);
2288
2289         assemblyb = moduleb->assemblyb;
2290         assembly = moduleb->dynamic_image;
2291         domain = mono_object_domain (assemblyb);
2292
2293         if (assembly->text_rva)
2294                 return TRUE;
2295
2296         assembly->text_rva = START_TEXT_RVA;
2297
2298         if (moduleb->is_main) {
2299                 mono_image_emit_manifest (moduleb, error);
2300                 return_val_if_nok (error, FALSE);
2301         }
2302
2303         table = &assembly->tables [MONO_TABLE_TYPEDEF];
2304         table->rows = 1; /* .<Module> */
2305         table->next_idx++;
2306         alloc_table (table, table->rows);
2307         /*
2308          * Set the first entry.
2309          */
2310         values = table->values + table->columns;
2311         values [MONO_TYPEDEF_FLAGS] = 0;
2312         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
2313         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
2314         values [MONO_TYPEDEF_EXTENDS] = 0;
2315         values [MONO_TYPEDEF_FIELD_LIST] = 1;
2316         values [MONO_TYPEDEF_METHOD_LIST] = 1;
2317
2318         /* 
2319          * handle global methods 
2320          * FIXME: test what to do when global methods are defined in multiple modules.
2321          */
2322         if (moduleb->global_methods) {
2323                 table = &assembly->tables [MONO_TABLE_METHOD];
2324                 table->rows += mono_array_length (moduleb->global_methods);
2325                 alloc_table (table, table->rows);
2326                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
2327                         if (!mono_image_get_method_info (
2328                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
2329                                 goto leave;
2330                 }
2331         }
2332         if (moduleb->global_fields) {
2333                 table = &assembly->tables [MONO_TABLE_FIELD];
2334                 table->rows += mono_array_length (moduleb->global_fields);
2335                 alloc_table (table, table->rows);
2336                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
2337                         mono_image_get_field_info (
2338                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
2339                                 error);
2340                         if (!is_ok (error))
2341                                 goto leave;
2342                 }
2343         }
2344
2345         table = &assembly->tables [MONO_TABLE_MODULE];
2346         alloc_table (table, 1);
2347         mono_image_fill_module_table (domain, moduleb, assembly, error);
2348         if (!is_ok (error))
2349                 goto leave;
2350
2351         /* Collect all types into a list sorted by their table_idx */
2352         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
2353
2354         if (moduleb->types)
2355                 for (i = 0; i < moduleb->num_types; ++i) {
2356                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
2357                         collect_types (&types, type);
2358                 }
2359
2360         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
2361         table = &assembly->tables [MONO_TABLE_TYPEDEF];
2362         table->rows += mono_ptr_array_size (types);
2363         alloc_table (table, table->rows);
2364
2365         /*
2366          * Emit type names + namespaces at one place inside the string heap,
2367          * so load_class_names () needs to touch fewer pages.
2368          */
2369         for (i = 0; i < mono_ptr_array_size (types); ++i) {
2370                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
2371                 string_heap_insert_mstring (&assembly->sheap, tb->nspace, error);
2372                 if (!is_ok (error))
2373                         goto leave_types;
2374         }
2375         for (i = 0; i < mono_ptr_array_size (types); ++i) {
2376                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
2377                 string_heap_insert_mstring (&assembly->sheap, tb->name, error);
2378                 if (!is_ok (error))
2379                         goto leave_types;
2380         }
2381
2382         for (i = 0; i < mono_ptr_array_size (types); ++i) {
2383                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
2384                 if (!mono_image_get_type_info (domain, type, assembly, error))
2385                         goto leave_types;
2386         }
2387
2388         /* 
2389          * table->rows is already set above and in mono_image_fill_module_table.
2390          */
2391         /* add all the custom attributes at the end, once all the indexes are stable */
2392         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
2393                 goto leave_types;
2394
2395         /* CAS assembly permissions */
2396         if (assemblyb->permissions_minimum)
2397                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
2398         if (assemblyb->permissions_optional)
2399                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
2400         if (assemblyb->permissions_refused)
2401                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
2402
2403         if (!module_add_cattrs (assembly, moduleb, error))
2404                 goto leave_types;
2405
2406         /* fixup tokens */
2407         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
2408
2409         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
2410          * the final tokens and don't need another fixup pass. */
2411
2412         if (moduleb->global_methods) {
2413                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
2414                         MonoReflectionMethodBuilder *mb = mono_array_get (
2415                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
2416                         if (!mono_image_add_methodimpl (assembly, mb, error))
2417                                 goto leave_types;
2418                 }
2419         }
2420
2421         for (i = 0; i < mono_ptr_array_size (types); ++i) {
2422                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
2423                 if (type->methods) {
2424                         for (j = 0; j < type->num_methods; ++j) {
2425                                 MonoReflectionMethodBuilder *mb = mono_array_get (
2426                                         type->methods, MonoReflectionMethodBuilder*, j);
2427
2428                                 if (!mono_image_add_methodimpl (assembly, mb, error))
2429                                         goto leave_types;
2430                         }
2431                 }
2432         }
2433
2434         fixup_cattrs (assembly);
2435
2436 leave_types:
2437         mono_ptr_array_destroy (types);
2438 leave:
2439
2440         return mono_error_ok (error);
2441 }
2442
2443 #else /* DISABLE_REFLECTION_EMIT_SAVE */
2444
2445 gboolean
2446 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
2447 {
2448         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
2449 }
2450
2451 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
2452
2453 #ifndef DISABLE_REFLECTION_EMIT_SAVE
2454
2455 static int
2456 calc_section_size (MonoDynamicImage *assembly)
2457 {
2458         int nsections = 0;
2459
2460         /* alignment constraints */
2461         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
2462         g_assert ((assembly->code.index % 4) == 0);
2463         assembly->meta_size += 3;
2464         assembly->meta_size &= ~3;
2465         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
2466         g_assert ((assembly->resources.index % 4) == 0);
2467
2468         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
2469         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
2470         nsections++;
2471
2472         if (assembly->win32_res) {
2473                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
2474
2475                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
2476                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
2477                 nsections++;
2478         }
2479
2480         assembly->sections [MONO_SECTION_RELOC].size = 12;
2481         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
2482         nsections++;
2483
2484         return nsections;
2485 }
2486
2487 typedef struct {
2488         guint32 id;
2489         guint32 offset;
2490         GSList *children;
2491         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
2492 } ResTreeNode;
2493
2494 static int
2495 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
2496 {
2497         ResTreeNode *t1 = (ResTreeNode*)a;
2498         ResTreeNode *t2 = (ResTreeNode*)b;
2499
2500         return t1->id - t2->id;
2501 }
2502
2503 /*
2504  * resource_tree_create:
2505  *
2506  *  Organize the resources into a resource tree.
2507  */
2508 static ResTreeNode *
2509 resource_tree_create (MonoArray *win32_resources)
2510 {
2511         ResTreeNode *tree, *res_node, *type_node, *lang_node;
2512         GSList *l;
2513         int i;
2514
2515         tree = g_new0 (ResTreeNode, 1);
2516         
2517         for (i = 0; i < mono_array_length (win32_resources); ++i) {
2518                 MonoReflectionWin32Resource *win32_res =
2519                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
2520
2521                 /* Create node */
2522
2523                 /* FIXME: BUG: this stores managed references in unmanaged memory */
2524                 lang_node = g_new0 (ResTreeNode, 1);
2525                 lang_node->id = win32_res->lang_id;
2526                 lang_node->win32_res = win32_res;
2527
2528                 /* Create type node if neccesary */
2529                 type_node = NULL;
2530                 for (l = tree->children; l; l = l->next)
2531                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
2532                                 type_node = (ResTreeNode*)l->data;
2533                                 break;
2534                         }
2535
2536                 if (!type_node) {
2537                         type_node = g_new0 (ResTreeNode, 1);
2538                         type_node->id = win32_res->res_type;
2539
2540                         /* 
2541                          * The resource types have to be sorted otherwise
2542                          * Windows Explorer can't display the version information.
2543                          */
2544                         tree->children = g_slist_insert_sorted (tree->children, 
2545                                 type_node, resource_tree_compare_by_id);
2546                 }
2547
2548                 /* Create res node if neccesary */
2549                 res_node = NULL;
2550                 for (l = type_node->children; l; l = l->next)
2551                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
2552                                 res_node = (ResTreeNode*)l->data;
2553                                 break;
2554                         }
2555
2556                 if (!res_node) {
2557                         res_node = g_new0 (ResTreeNode, 1);
2558                         res_node->id = win32_res->res_id;
2559                         type_node->children = g_slist_append (type_node->children, res_node);
2560                 }
2561
2562                 res_node->children = g_slist_append (res_node->children, lang_node);
2563         }
2564
2565         return tree;
2566 }
2567
2568 /*
2569  * resource_tree_encode:
2570  * 
2571  *   Encode the resource tree into the format used in the PE file.
2572  */
2573 static void
2574 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
2575 {
2576         char *entries;
2577         MonoPEResourceDir dir;
2578         MonoPEResourceDirEntry dir_entry;
2579         MonoPEResourceDataEntry data_entry;
2580         GSList *l;
2581         guint32 res_id_entries;
2582
2583         /*
2584          * For the format of the resource directory, see the article
2585          * "An In-Depth Look into the Win32 Portable Executable File Format" by
2586          * Matt Pietrek
2587          */
2588
2589         memset (&dir, 0, sizeof (dir));
2590         memset (&dir_entry, 0, sizeof (dir_entry));
2591         memset (&data_entry, 0, sizeof (data_entry));
2592
2593         g_assert (sizeof (dir) == 16);
2594         g_assert (sizeof (dir_entry) == 8);
2595         g_assert (sizeof (data_entry) == 16);
2596
2597         node->offset = p - begin;
2598
2599         /* IMAGE_RESOURCE_DIRECTORY */
2600         res_id_entries = g_slist_length (node->children);
2601         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
2602
2603         memcpy (p, &dir, sizeof (dir));
2604         p += sizeof (dir);
2605
2606         /* Reserve space for entries */
2607         entries = p;
2608         p += sizeof (dir_entry) * res_id_entries;
2609
2610         /* Write children */
2611         for (l = node->children; l; l = l->next) {
2612                 ResTreeNode *child = (ResTreeNode*)l->data;
2613
2614                 if (child->win32_res) {
2615                         guint32 size;
2616
2617                         child->offset = p - begin;
2618
2619                         /* IMAGE_RESOURCE_DATA_ENTRY */
2620                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
2621                         size = mono_array_length (child->win32_res->res_data);
2622                         data_entry.rde_size = GUINT32_TO_LE (size);
2623
2624                         memcpy (p, &data_entry, sizeof (data_entry));
2625                         p += sizeof (data_entry);
2626
2627                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
2628                         p += size;
2629                 } else {
2630                         resource_tree_encode (child, begin, p, &p);
2631                 }
2632         }
2633
2634         /* IMAGE_RESOURCE_ENTRY */
2635         for (l = node->children; l; l = l->next) {
2636                 ResTreeNode *child = (ResTreeNode*)l->data;
2637
2638                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
2639                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
2640
2641                 memcpy (entries, &dir_entry, sizeof (dir_entry));
2642                 entries += sizeof (dir_entry);
2643         }
2644
2645         *endbuf = p;
2646 }
2647
2648 static void
2649 resource_tree_free (ResTreeNode * node)
2650 {
2651         GSList * list;
2652         for (list = node->children; list; list = list->next)
2653                 resource_tree_free ((ResTreeNode*)list->data);
2654         g_slist_free(node->children);
2655         g_free (node);
2656 }
2657
2658 static void
2659 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
2660 {
2661         char *buf;
2662         char *p;
2663         guint32 size, i;
2664         MonoReflectionWin32Resource *win32_res;
2665         ResTreeNode *tree;
2666
2667         if (!assemblyb->win32_resources)
2668                 return;
2669
2670         /*
2671          * Resources are stored in a three level tree inside the PE file.
2672          * - level one contains a node for each type of resource
2673          * - level two contains a node for each resource
2674          * - level three contains a node for each instance of a resource for a
2675          *   specific language.
2676          */
2677
2678         tree = resource_tree_create (assemblyb->win32_resources);
2679
2680         /* Estimate the size of the encoded tree */
2681         size = 0;
2682         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
2683                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
2684                 size += mono_array_length (win32_res->res_data);
2685         }
2686         /* Directory structure */
2687         size += mono_array_length (assemblyb->win32_resources) * 256;
2688         p = buf = (char *)g_malloc (size);
2689
2690         resource_tree_encode (tree, p, p, &p);
2691
2692         g_assert (p - buf <= size);
2693
2694         assembly->win32_res = (char *)g_malloc (p - buf);
2695         assembly->win32_res_size = p - buf;
2696         memcpy (assembly->win32_res, buf, p - buf);
2697
2698         g_free (buf);
2699         resource_tree_free (tree);
2700 }
2701
2702 static void
2703 fixup_resource_directory (char *res_section, char *p, guint32 rva)
2704 {
2705         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
2706         int i;
2707
2708         p += sizeof (MonoPEResourceDir);
2709         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
2710                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
2711                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
2712                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
2713                         fixup_resource_directory (res_section, child, rva);
2714                 } else {
2715                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
2716                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
2717                 }
2718
2719                 p += sizeof (MonoPEResourceDirEntry);
2720         }
2721 }
2722
2723 static void
2724 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
2725 {
2726         guint32 dummy;
2727         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
2728                 g_error ("WriteFile returned %d\n", GetLastError ());
2729 }
2730
2731 /*
2732  * mono_image_create_pefile:
2733  * @mb: a module builder object
2734  * 
2735  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
2736  * assembly->pefile where it can be easily retrieved later in chunks.
2737  */
2738 gboolean
2739 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
2740 {
2741         MonoMSDOSHeader *msdos;
2742         MonoDotNetHeader *header;
2743         MonoSectionTable *section;
2744         MonoCLIHeader *cli_header;
2745         guint32 size, image_size, virtual_base, text_offset;
2746         guint32 header_start, section_start, file_offset, virtual_offset;
2747         MonoDynamicImage *assembly;
2748         MonoReflectionAssemblyBuilder *assemblyb;
2749         MonoDynamicStream pefile_stream = {0};
2750         MonoDynamicStream *pefile = &pefile_stream;
2751         int i, nsections;
2752         guint32 *rva, value;
2753         guchar *p;
2754         static const unsigned char msheader[] = {
2755                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
2756                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2757                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2758                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
2759                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
2760                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
2761                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
2762                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2763         };
2764
2765         mono_error_init (error);
2766
2767         assemblyb = mb->assemblyb;
2768
2769         mono_reflection_dynimage_basic_init (assemblyb);
2770         assembly = mb->dynamic_image;
2771
2772         assembly->pe_kind = assemblyb->pe_kind;
2773         assembly->machine = assemblyb->machine;
2774         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
2775         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
2776         
2777         if (!mono_image_build_metadata (mb, error))
2778                 return FALSE;
2779         
2780
2781         if (mb->is_main && assemblyb->resources) {
2782                 int len = mono_array_length (assemblyb->resources);
2783                 for (i = 0; i < len; ++i) {
2784                         if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i), error))
2785                                 return FALSE;
2786                 }
2787         }
2788
2789         if (mb->resources) {
2790                 int len = mono_array_length (mb->resources);
2791                 for (i = 0; i < len; ++i) {
2792                         if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i), error))
2793                                 return FALSE;
2794                 }
2795         }
2796
2797         if (!build_compressed_metadata (assembly, error))
2798                 return FALSE;
2799
2800         if (mb->is_main)
2801                 assembly_add_win32_resources (assembly, assemblyb);
2802
2803         nsections = calc_section_size (assembly);
2804         
2805         /* The DOS header and stub */
2806         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
2807         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
2808
2809         /* the dotnet header */
2810         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
2811
2812         /* the section tables */
2813         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
2814
2815         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
2816         virtual_offset = VIRT_ALIGN;
2817         image_size = 0;
2818
2819         for (i = 0; i < MONO_SECTION_MAX; ++i) {
2820                 if (!assembly->sections [i].size)
2821                         continue;
2822                 /* align offsets */
2823                 file_offset += FILE_ALIGN - 1;
2824                 file_offset &= ~(FILE_ALIGN - 1);
2825                 virtual_offset += VIRT_ALIGN - 1;
2826                 virtual_offset &= ~(VIRT_ALIGN - 1);
2827
2828                 assembly->sections [i].offset = file_offset;
2829                 assembly->sections [i].rva = virtual_offset;
2830
2831                 file_offset += assembly->sections [i].size;
2832                 virtual_offset += assembly->sections [i].size;
2833                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
2834         }
2835
2836         file_offset += FILE_ALIGN - 1;
2837         file_offset &= ~(FILE_ALIGN - 1);
2838
2839         image_size += section_start + sizeof (MonoSectionTable) * nsections;
2840
2841         /* back-patch info */
2842         msdos = (MonoMSDOSHeader*)pefile->data;
2843         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
2844
2845         header = (MonoDotNetHeader*)(pefile->data + header_start);
2846         header->pesig [0] = 'P';
2847         header->pesig [1] = 'E';
2848         
2849         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
2850         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
2851         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
2852         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
2853         if (assemblyb->pekind == 1) {
2854                 /* it's a dll */
2855                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
2856         } else {
2857                 /* it's an exe */
2858                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
2859         }
2860
2861         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
2862
2863         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
2864         header->pe.pe_major = 6;
2865         header->pe.pe_minor = 0;
2866         size = assembly->sections [MONO_SECTION_TEXT].size;
2867         size += FILE_ALIGN - 1;
2868         size &= ~(FILE_ALIGN - 1);
2869         header->pe.pe_code_size = GUINT32_FROM_LE(size);
2870         size = assembly->sections [MONO_SECTION_RSRC].size;
2871         size += FILE_ALIGN - 1;
2872         size &= ~(FILE_ALIGN - 1);
2873         header->pe.pe_data_size = GUINT32_FROM_LE(size);
2874         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
2875         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
2876         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2877         /* pe_rva_entry_point always at the beginning of the text section */
2878         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
2879
2880         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
2881         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
2882         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
2883         header->nt.pe_os_major = GUINT16_FROM_LE (4);
2884         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
2885         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
2886         size = section_start;
2887         size += FILE_ALIGN - 1;
2888         size &= ~(FILE_ALIGN - 1);
2889         header->nt.pe_header_size = GUINT32_FROM_LE (size);
2890         size = image_size;
2891         size += VIRT_ALIGN - 1;
2892         size &= ~(VIRT_ALIGN - 1);
2893         header->nt.pe_image_size = GUINT32_FROM_LE (size);
2894
2895         /*
2896         // Translate the PEFileKind value to the value expected by the Windows loader
2897         */
2898         {
2899                 short kind;
2900
2901                 /*
2902                 // PEFileKinds.Dll == 1
2903                 // PEFileKinds.ConsoleApplication == 2
2904                 // PEFileKinds.WindowApplication == 3
2905                 //
2906                 // need to get:
2907                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
2908                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
2909                 */
2910                 if (assemblyb->pekind == 3)
2911                         kind = 2;
2912                 else
2913                         kind = 3;
2914                 
2915                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
2916         }    
2917         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
2918         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
2919         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
2920         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
2921         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
2922         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
2923
2924         /* fill data directory entries */
2925
2926         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
2927         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2928
2929         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
2930         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
2931
2932         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
2933         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
2934         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
2935         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2936         /* patch entrypoint name */
2937         if (assemblyb->pekind == 1)
2938                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
2939         else
2940                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
2941         /* patch imported function RVA name */
2942         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
2943         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
2944
2945         /* the import table */
2946         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
2947         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
2948         /* patch imported dll RVA name and other entries in the dir */
2949         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
2950         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
2951         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
2952         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2953         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
2954         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
2955
2956         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
2957         value = (assembly->text_rva + assembly->imp_names_offset);
2958         *p++ = (value) & 0xff;
2959         *p++ = (value >> 8) & (0xff);
2960         *p++ = (value >> 16) & (0xff);
2961         *p++ = (value >> 24) & (0xff);
2962
2963         /* the CLI header info */
2964         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
2965         cli_header->ch_size = GUINT32_FROM_LE (72);
2966         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
2967         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
2968         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
2969         if (assemblyb->entry_point) {
2970                 guint32 table_idx = 0;
2971                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
2972                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
2973                         table_idx = methodb->table_idx;
2974                 } else {
2975                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
2976                 }
2977                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
2978         } else {
2979                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
2980         }
2981         /* The embedded managed resources */
2982         text_offset = assembly->text_rva + assembly->code.index;
2983         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
2984         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
2985         text_offset += assembly->resources.index;
2986         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
2987         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
2988         text_offset += assembly->meta_size;
2989         if (assembly->strong_name_size) {
2990                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
2991                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
2992                 text_offset += assembly->strong_name_size;
2993         }
2994
2995         /* write the section tables and section content */
2996         section = (MonoSectionTable*)(pefile->data + section_start);
2997         for (i = 0; i < MONO_SECTION_MAX; ++i) {
2998                 static const char section_names [][7] = {
2999                         ".text", ".rsrc", ".reloc"
3000                 };
3001                 if (!assembly->sections [i].size)
3002                         continue;
3003                 strcpy (section->st_name, section_names [i]);
3004                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
3005                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
3006                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
3007                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
3008                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
3009                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
3010                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
3011                 section ++;
3012         }
3013         
3014         checked_write_file (file, pefile->data, pefile->index);
3015         
3016         mono_dynamic_stream_reset (pefile);
3017         
3018         for (i = 0; i < MONO_SECTION_MAX; ++i) {
3019                 if (!assembly->sections [i].size)
3020                         continue;
3021                 
3022                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
3023                         g_error ("SetFilePointer returned %d\n", GetLastError ());
3024                 
3025                 switch (i) {
3026                 case MONO_SECTION_TEXT:
3027                         /* patch entry point */
3028                         p = (guchar*)(assembly->code.data + 2);
3029                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
3030                         *p++ = (value) & 0xff;
3031                         *p++ = (value >> 8) & 0xff;
3032                         *p++ = (value >> 16) & 0xff;
3033                         *p++ = (value >> 24) & 0xff;
3034                 
3035                         checked_write_file (file, assembly->code.data, assembly->code.index);
3036                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
3037                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
3038                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
3039                                 
3040
3041                         g_free (assembly->image.raw_metadata);
3042                         break;
3043                 case MONO_SECTION_RELOC: {
3044                         struct {
3045                                 guint32 page_rva;
3046                                 guint32 block_size;
3047                                 guint16 type_and_offset;
3048                                 guint16 term;
3049                         } reloc;
3050                         
3051                         g_assert (sizeof (reloc) == 12);
3052                         
3053                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
3054                         reloc.block_size = GUINT32_FROM_LE (12);
3055                         
3056                         /* 
3057                          * the entrypoint is always at the start of the text section 
3058                          * 3 is IMAGE_REL_BASED_HIGHLOW
3059                          * 2 is patch_size_rva - text_rva
3060                          */
3061                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
3062                         reloc.term = 0;
3063                         
3064                         checked_write_file (file, &reloc, sizeof (reloc));
3065                         
3066                         break;
3067                 }
3068                 case MONO_SECTION_RSRC:
3069                         if (assembly->win32_res) {
3070
3071                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
3072                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
3073                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
3074                         }
3075                         break;
3076                 default:
3077                         g_assert_not_reached ();
3078                 }
3079         }
3080         
3081         /* check that the file is properly padded */
3082         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
3083                 g_error ("SetFilePointer returned %d\n", GetLastError ());
3084         if (! SetEndOfFile (file))
3085                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
3086         
3087         mono_dynamic_stream_reset (&assembly->code);
3088         mono_dynamic_stream_reset (&assembly->us);
3089         mono_dynamic_stream_reset (&assembly->blob);
3090         mono_dynamic_stream_reset (&assembly->guid);
3091         mono_dynamic_stream_reset (&assembly->sheap);
3092
3093         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
3094         g_hash_table_destroy (assembly->blob_cache);
3095         assembly->blob_cache = NULL;
3096
3097         return TRUE;
3098 }
3099
3100 #else /* DISABLE_REFLECTION_EMIT_SAVE */
3101
3102 gboolean
3103 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
3104 {
3105         g_assert_not_reached ();
3106 }
3107
3108 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
3109