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