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