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