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