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