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