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