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