Merge pull request #5675 from mono/glib-debug-symbols
[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_TYPEREF:
1763                         g_assert (!strcmp (iltoken->member->vtable->klass->name, "RuntimeType"));
1764                         MonoClass *k = mono_class_from_mono_type (((MonoReflectionType*)iltoken->member)->type);
1765                         MonoObject *obj = mono_class_get_ref_info_raw (k); /* FIXME use handles */
1766                         g_assert (obj);
1767                         g_assert (!strcmp (mono_object_class (obj)->name, "TypeBuilder"));
1768                         g_assert (((MonoReflectionTypeBuilder*)obj)->module->dynamic_image != assembly);
1769                         continue;
1770                 case MONO_TABLE_MEMBERREF:
1771                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
1772                                 am = (MonoReflectionArrayMethod*)iltoken->member;
1773                                 idx = am->table_idx;
1774                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
1775                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
1776                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
1777                                 g_assert (mono_class_is_ginst (m->klass) || mono_class_is_gtd (m->klass));
1778                                 continue;
1779                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
1780                                 g_assert_not_reached ();
1781                                 continue;
1782                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
1783                                 continue;
1784                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
1785                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
1786                                 g_assert_not_reached ();
1787                                 continue;
1788                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
1789                                 g_assert_not_reached ();
1790                                 continue;
1791                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
1792                                 g_assert_not_reached ();
1793                                 continue;
1794                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
1795                                 g_assert_not_reached ();
1796                                 continue;
1797                         } else {
1798                                 g_assert_not_reached ();
1799                         }
1800                         break;
1801                 case MONO_TABLE_METHODSPEC:
1802                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
1803                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
1804                                 g_assert (mono_method_signature (m)->generic_param_count);
1805                                 continue;
1806                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
1807                                 g_assert_not_reached ();
1808                                 continue;
1809                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
1810                                 g_assert_not_reached ();
1811                                 continue;
1812                         } else {
1813                                 g_assert_not_reached ();
1814                         }
1815                         break;
1816                 case MONO_TABLE_TYPESPEC:
1817                         if (!strcmp (iltoken->member->vtable->klass->name, "RuntimeType")) {
1818                                 continue;
1819                         } else {
1820                                 g_assert_not_reached ();
1821                         }
1822                         break;
1823                 default:
1824                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
1825                 }
1826                 target [0] = idx & 0xff;
1827                 target [1] = (idx >> 8) & 0xff;
1828                 target [2] = (idx >> 16) & 0xff;
1829         }
1830 }
1831
1832 /*
1833  * fixup_cattrs:
1834  *
1835  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
1836  * value is not known when the table is emitted.
1837  */
1838 static void
1839 fixup_cattrs (MonoDynamicImage *assembly)
1840 {
1841         MonoDynamicTable *table;
1842         guint32 *values;
1843         guint32 type, i, idx, token;
1844         MonoObject *ctor;
1845
1846         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1847
1848         for (i = 0; i < table->rows; ++i) {
1849                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
1850
1851                 type = values [MONO_CUSTOM_ATTR_TYPE];
1852                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
1853                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
1854                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
1855                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
1856                         g_assert (ctor);
1857
1858                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
1859                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
1860                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
1861                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1862                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
1863                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
1864                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
1865                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1866                         }
1867                 }
1868         }
1869 }
1870
1871 static gboolean
1872 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation, MonoError *error)
1873 {
1874         MonoDynamicTable *table;
1875         guint32 *values;
1876
1877         error_init (error);
1878
1879         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
1880         table->rows++;
1881         alloc_table (table, table->rows);
1882         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
1883         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
1884         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
1885         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name, error);
1886         return_val_if_nok (error, FALSE);
1887         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
1888         table->next_idx++;
1889         return TRUE;
1890 }
1891
1892 static gboolean
1893 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, MonoError *error)
1894 {
1895         MonoDynamicTable *table;
1896         guint32 *values;
1897         char blob_size [6];
1898         guchar hash [20];
1899         char *b = blob_size;
1900         char *name, *sname;
1901         guint32 idx, offset;
1902
1903         error_init (error);
1904
1905         if (rsrc->filename) {
1906                 name = mono_string_to_utf8_checked (rsrc->filename, error);
1907                 return_val_if_nok (error, FALSE);
1908                 sname = g_path_get_basename (name);
1909         
1910                 table = &assembly->tables [MONO_TABLE_FILE];
1911                 table->rows++;
1912                 alloc_table (table, table->rows);
1913                 values = table->values + table->next_idx * MONO_FILE_SIZE;
1914                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
1915                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
1916                 g_free (sname);
1917
1918                 mono_sha1_get_digest_from_file (name, hash);
1919                 mono_metadata_encode_value (20, b, &b);
1920                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1921                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
1922                 g_free (name);
1923                 idx = table->next_idx++;
1924                 rsrc->offset = 0;
1925                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
1926         } else {
1927                 char sizebuf [4];
1928                 char *data;
1929                 guint len;
1930                 if (rsrc->data) {
1931                         data = mono_array_addr (rsrc->data, char, 0);
1932                         len = mono_array_length (rsrc->data);
1933                 } else {
1934                         data = NULL;
1935                         len = 0;
1936                 }
1937                 offset = len;
1938                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
1939                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
1940                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
1941                 mono_image_add_stream_data (&assembly->resources, data, len);
1942
1943                 if (!mb->is_main)
1944                         /* 
1945                          * The entry should be emitted into the MANIFESTRESOURCE table of 
1946                          * the main module, but that needs to reference the FILE table
1947                          * which isn't emitted yet.
1948                          */
1949                         return TRUE;
1950                 else
1951                         idx = 0;
1952         }
1953
1954         return assembly_add_resource_manifest (mb, assembly, rsrc, idx, error);
1955 }
1956
1957 static gboolean
1958 set_version_from_string (MonoString *version, guint32 *values, MonoError *error)
1959 {
1960         gchar *ver, *p, *str;
1961         guint32 i;
1962         
1963         error_init (error);
1964
1965         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
1966         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
1967         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
1968         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
1969         if (!version)
1970                 return TRUE;
1971         ver = str = mono_string_to_utf8_checked (version, error);
1972         return_val_if_nok (error, FALSE);
1973         for (i = 0; i < 4; ++i) {
1974                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
1975                 switch (*p) {
1976                 case '.':
1977                         p++;
1978                         break;
1979                 case '*':
1980                         /* handle Revision and Build */
1981                         p++;
1982                         break;
1983                 }
1984                 ver = p;
1985         }
1986         g_free (str);
1987         return TRUE;
1988 }
1989
1990 static guint32
1991 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
1992         gsize len;
1993         guint32 token = 0;
1994         char blob_size [6];
1995         char *b = blob_size;
1996
1997         if (!pkey)
1998                 return token;
1999
2000         len = mono_array_length (pkey);
2001         mono_metadata_encode_value (len, b, &b);
2002         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
2003         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
2004
2005         assembly->public_key = (guint8 *)g_malloc (len);
2006         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
2007         assembly->public_key_len = len;
2008
2009         /* Special case: check for ECMA key (16 bytes) */
2010         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
2011                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
2012                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
2013         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
2014                 /* minimum key size (in 2.0) is 384 bits */
2015                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
2016         } else {
2017                 /* FIXME - verifier */
2018                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
2019                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
2020         }
2021         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
2022
2023         return token;
2024 }
2025
2026 static gboolean
2027 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
2028 {
2029         MonoDynamicTable *table;
2030         MonoDynamicImage *assembly;
2031         MonoReflectionAssemblyBuilder *assemblyb;
2032         MonoDomain *domain;
2033         guint32 *values;
2034         int i;
2035         guint32 module_index;
2036
2037         error_init (error);
2038
2039         assemblyb = moduleb->assemblyb;
2040         assembly = moduleb->dynamic_image;
2041         domain = mono_object_domain (assemblyb);
2042
2043         /* Emit ASSEMBLY table */
2044         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
2045         alloc_table (table, 1);
2046         values = table->values + MONO_ASSEMBLY_SIZE;
2047         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
2048         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name, error);
2049         return_val_if_nok (error, FALSE);
2050         if (assemblyb->culture) {
2051                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture, error);
2052                 return_val_if_nok (error, FALSE);
2053         } else {
2054                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
2055         }
2056         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
2057         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
2058         if (!set_version_from_string (assemblyb->version, values, error))
2059                 return FALSE;
2060
2061         /* Emit FILE + EXPORTED_TYPE table */
2062         module_index = 0;
2063         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
2064                 int j;
2065                 MonoReflectionModuleBuilder *file_module = 
2066                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
2067                 if (file_module != moduleb) {
2068                         if (!mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly, error))
2069                                 return FALSE;
2070                         module_index ++;
2071                         if (file_module->types) {
2072                                 for (j = 0; j < file_module->num_types; ++j) {
2073                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
2074                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
2075                                         return_val_if_nok (error, FALSE);
2076                                 }
2077                         }
2078                 }
2079         }
2080         if (assemblyb->loaded_modules) {
2081                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
2082                         MonoReflectionModule *file_module = 
2083                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
2084                         if (!mono_image_fill_file_table (domain, file_module, assembly, error))
2085                                 return FALSE;
2086                         module_index ++;
2087                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
2088                 }
2089         }
2090         if (assemblyb->type_forwarders)
2091                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
2092
2093         /* Emit MANIFESTRESOURCE table */
2094         module_index = 0;
2095         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
2096                 int j;
2097                 MonoReflectionModuleBuilder *file_module = 
2098                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
2099                 /* The table for the main module is emitted later */
2100                 if (file_module != moduleb) {
2101                         module_index ++;
2102                         if (file_module->resources) {
2103                                 int len = mono_array_length (file_module->resources);
2104                                 for (j = 0; j < len; ++j) {
2105                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
2106                                         if (!assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS), error))
2107                                                 return FALSE;
2108                                 }
2109                         }
2110                 }
2111         }
2112         return TRUE;
2113 }
2114
2115 #ifndef DISABLE_REFLECTION_EMIT_SAVE
2116
2117 /*
2118  * Insert into the metadata tables all the info about the TypeBuilder tb.
2119  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2120  */
2121 static gboolean
2122 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
2123 {
2124         MonoDynamicTable *table;
2125         guint *values;
2126         int i, is_object = 0, is_system = 0;
2127         char *n;
2128
2129         error_init (error);
2130
2131         table = &assembly->tables [MONO_TABLE_TYPEDEF];
2132         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2133         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2134         n = mono_string_to_utf8_checked (tb->name, error);
2135         return_val_if_nok (error, FALSE);
2136         if (strcmp (n, "Object") == 0)
2137                 is_object++;
2138         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2139         g_free (n);
2140         n = mono_string_to_utf8_checked (tb->nspace, error);
2141         return_val_if_nok (error, FALSE);
2142         if (strcmp (n, "System") == 0)
2143                 is_system++;
2144         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2145         g_free (n);
2146         if (tb->parent && !(is_system && is_object) && 
2147                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2148                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
2149                 return_val_if_nok (error, FALSE);
2150                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
2151         } else {
2152                 values [MONO_TYPEDEF_EXTENDS] = 0;
2153         }
2154         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2155         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2156
2157         /*
2158          * if we have explicitlayout or sequentiallayouts, output data in the
2159          * ClassLayout table.
2160          */
2161         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2162                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
2163                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2164                 table->rows++;
2165                 alloc_table (table, table->rows);
2166                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2167                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2168                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2169                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2170         }
2171
2172         /* handle interfaces */
2173         if (tb->interfaces) {
2174                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2175                 i = table->rows;
2176                 table->rows += mono_array_length (tb->interfaces);
2177                 alloc_table (table, table->rows);
2178                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2179                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2180                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2181                         MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
2182                         return_val_if_nok (error, FALSE);
2183                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2184                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
2185                         values += MONO_INTERFACEIMPL_SIZE;
2186                 }
2187         }
2188
2189         /* handle fields */
2190         if (tb->fields) {
2191                 table = &assembly->tables [MONO_TABLE_FIELD];
2192                 table->rows += tb->num_fields;
2193                 alloc_table (table, table->rows);
2194                 for (i = 0; i < tb->num_fields; ++i) {
2195                         mono_image_get_field_info (
2196                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
2197                         return_val_if_nok (error, FALSE);
2198                 }
2199         }
2200
2201         /* handle constructors */
2202         if (tb->ctors) {
2203                 table = &assembly->tables [MONO_TABLE_METHOD];
2204                 table->rows += mono_array_length (tb->ctors);
2205                 alloc_table (table, table->rows);
2206                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2207                         if (!mono_image_get_ctor_info (domain,
2208                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
2209                                                        assembly, error))
2210                                 return FALSE;
2211                 }
2212         }
2213
2214         /* handle methods */
2215         if (tb->methods) {
2216                 table = &assembly->tables [MONO_TABLE_METHOD];
2217                 table->rows += tb->num_methods;
2218                 alloc_table (table, table->rows);
2219                 for (i = 0; i < tb->num_methods; ++i) {
2220                         if (!mono_image_get_method_info (
2221                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
2222                                 return FALSE;
2223                 }
2224         }
2225
2226         /* Do the same with properties etc.. */
2227         if (tb->events && mono_array_length (tb->events)) {
2228                 table = &assembly->tables [MONO_TABLE_EVENT];
2229                 table->rows += mono_array_length (tb->events);
2230                 alloc_table (table, table->rows);
2231                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2232                 table->rows ++;
2233                 alloc_table (table, table->rows);
2234                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2235                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2236                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2237                 for (i = 0; i < mono_array_length (tb->events); ++i) {
2238                         mono_image_get_event_info (
2239                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
2240                         return_val_if_nok (error, FALSE);
2241                 }
2242         }
2243         if (tb->properties && mono_array_length (tb->properties)) {
2244                 table = &assembly->tables [MONO_TABLE_PROPERTY];
2245                 table->rows += mono_array_length (tb->properties);
2246                 alloc_table (table, table->rows);
2247                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2248                 table->rows ++;
2249                 alloc_table (table, table->rows);
2250                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2251                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2252                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2253                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2254                         mono_image_get_property_info (
2255                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
2256                         return_val_if_nok (error, FALSE);
2257                 }
2258         }
2259
2260         /* handle generic parameters */
2261         if (tb->generic_params) {
2262                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2263                 table->rows += mono_array_length (tb->generic_params);
2264                 alloc_table (table, table->rows);
2265                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2266                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2267
2268                         mono_image_get_generic_param_info (
2269                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2270                 }
2271         }
2272
2273         mono_image_add_decl_security (assembly, 
2274                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2275
2276         if (tb->subtypes) {
2277                 MonoDynamicTable *ntable;
2278                 
2279                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2280                 ntable->rows += mono_array_length (tb->subtypes);
2281                 alloc_table (ntable, ntable->rows);
2282                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2283
2284                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2285                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2286
2287                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2288                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2289                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2290                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2291                                 mono_string_to_utf8 (tb->name), tb->table_idx,
2292                                 ntable->next_idx, ntable->rows);*/
2293                         values += MONO_NESTED_CLASS_SIZE;
2294                         ntable->next_idx++;
2295                 }
2296         }
2297
2298         return TRUE;
2299 }
2300
2301
2302 /*
2303  * mono_image_build_metadata() will fill the info in all the needed metadata tables
2304  * for the modulebuilder @moduleb.
2305  * At the end of the process, method and field tokens are fixed up and the 
2306  * on-disk compressed metadata representation is created.
2307  * Return TRUE on success, or FALSE on failure and sets @error
2308  */
2309 gboolean
2310 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
2311 {
2312         MonoDynamicTable *table;
2313         MonoDynamicImage *assembly;
2314         MonoReflectionAssemblyBuilder *assemblyb;
2315         MonoDomain *domain;
2316         MonoPtrArray types;
2317         guint32 *values;
2318         int i, j;
2319
2320         error_init (error);
2321
2322         assemblyb = moduleb->assemblyb;
2323         assembly = moduleb->dynamic_image;
2324         domain = mono_object_domain (assemblyb);
2325
2326         if (assembly->text_rva)
2327                 return TRUE;
2328
2329         assembly->text_rva = START_TEXT_RVA;
2330
2331         if (moduleb->is_main) {
2332                 mono_image_emit_manifest (moduleb, error);
2333                 return_val_if_nok (error, FALSE);
2334         }
2335
2336         table = &assembly->tables [MONO_TABLE_TYPEDEF];
2337         table->rows = 1; /* .<Module> */
2338         table->next_idx++;
2339         alloc_table (table, table->rows);
2340         /*
2341          * Set the first entry.
2342          */
2343         values = table->values + table->columns;
2344         values [MONO_TYPEDEF_FLAGS] = 0;
2345         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
2346         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
2347         values [MONO_TYPEDEF_EXTENDS] = 0;
2348         values [MONO_TYPEDEF_FIELD_LIST] = 1;
2349         values [MONO_TYPEDEF_METHOD_LIST] = 1;
2350
2351         /* 
2352          * handle global methods 
2353          * FIXME: test what to do when global methods are defined in multiple modules.
2354          */
2355         if (moduleb->global_methods) {
2356                 table = &assembly->tables [MONO_TABLE_METHOD];
2357                 table->rows += mono_array_length (moduleb->global_methods);
2358                 alloc_table (table, table->rows);
2359                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
2360                         if (!mono_image_get_method_info (
2361                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
2362                                 goto leave;
2363                 }
2364         }
2365         if (moduleb->global_fields) {
2366                 table = &assembly->tables [MONO_TABLE_FIELD];
2367                 table->rows += mono_array_length (moduleb->global_fields);
2368                 alloc_table (table, table->rows);
2369                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
2370                         mono_image_get_field_info (
2371                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
2372                                 error);
2373                         if (!is_ok (error))
2374                                 goto leave;
2375                 }
2376         }
2377
2378         table = &assembly->tables [MONO_TABLE_MODULE];
2379         alloc_table (table, 1);
2380         mono_image_fill_module_table (domain, moduleb, assembly, error);
2381         if (!is_ok (error))
2382                 goto leave;
2383
2384         /* Collect all types into a list sorted by their table_idx */
2385         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
2386
2387         if (moduleb->types)
2388                 for (i = 0; i < moduleb->num_types; ++i) {
2389                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
2390                         collect_types (&types, type);
2391                 }
2392
2393         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
2394         table = &assembly->tables [MONO_TABLE_TYPEDEF];
2395         table->rows += mono_ptr_array_size (types);
2396         alloc_table (table, table->rows);
2397
2398         /*
2399          * Emit type names + namespaces at one place inside the string heap,
2400          * so load_class_names () needs to touch fewer pages.
2401          */
2402         for (i = 0; i < mono_ptr_array_size (types); ++i) {
2403                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
2404                 string_heap_insert_mstring (&assembly->sheap, tb->nspace, error);
2405                 if (!is_ok (error))
2406                         goto leave_types;
2407         }
2408         for (i = 0; i < mono_ptr_array_size (types); ++i) {
2409                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
2410                 string_heap_insert_mstring (&assembly->sheap, tb->name, error);
2411                 if (!is_ok (error))
2412                         goto leave_types;
2413         }
2414
2415         for (i = 0; i < mono_ptr_array_size (types); ++i) {
2416                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
2417                 if (!mono_image_get_type_info (domain, type, assembly, error))
2418                         goto leave_types;
2419         }
2420
2421         /* 
2422          * table->rows is already set above and in mono_image_fill_module_table.
2423          */
2424         /* add all the custom attributes at the end, once all the indexes are stable */
2425         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
2426                 goto leave_types;
2427
2428         /* CAS assembly permissions */
2429         if (assemblyb->permissions_minimum)
2430                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
2431         if (assemblyb->permissions_optional)
2432                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
2433         if (assemblyb->permissions_refused)
2434                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
2435
2436         if (!module_add_cattrs (assembly, moduleb, error))
2437                 goto leave_types;
2438
2439         /* fixup tokens */
2440         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
2441
2442         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
2443          * the final tokens and don't need another fixup pass. */
2444
2445         if (moduleb->global_methods) {
2446                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
2447                         MonoReflectionMethodBuilder *mb = mono_array_get (
2448                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
2449                         if (!mono_image_add_methodimpl (assembly, mb, error))
2450                                 goto leave_types;
2451                 }
2452         }
2453
2454         for (i = 0; i < mono_ptr_array_size (types); ++i) {
2455                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
2456                 if (type->methods) {
2457                         for (j = 0; j < type->num_methods; ++j) {
2458                                 MonoReflectionMethodBuilder *mb = mono_array_get (
2459                                         type->methods, MonoReflectionMethodBuilder*, j);
2460
2461                                 if (!mono_image_add_methodimpl (assembly, mb, error))
2462                                         goto leave_types;
2463                         }
2464                 }
2465         }
2466
2467         fixup_cattrs (assembly);
2468
2469 leave_types:
2470         mono_ptr_array_destroy (types);
2471 leave:
2472
2473         return mono_error_ok (error);
2474 }
2475
2476 #else /* DISABLE_REFLECTION_EMIT_SAVE */
2477
2478 gboolean
2479 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
2480 {
2481         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
2482 }
2483
2484 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
2485
2486 #ifndef DISABLE_REFLECTION_EMIT_SAVE
2487
2488 static int
2489 calc_section_size (MonoDynamicImage *assembly)
2490 {
2491         int nsections = 0;
2492
2493         /* alignment constraints */
2494         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
2495         g_assert ((assembly->code.index % 4) == 0);
2496         assembly->meta_size += 3;
2497         assembly->meta_size &= ~3;
2498         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
2499         g_assert ((assembly->resources.index % 4) == 0);
2500
2501         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
2502         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
2503         nsections++;
2504
2505         if (assembly->win32_res) {
2506                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
2507
2508                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
2509                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
2510                 nsections++;
2511         }
2512
2513         assembly->sections [MONO_SECTION_RELOC].size = 12;
2514         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
2515         nsections++;
2516
2517         return nsections;
2518 }
2519
2520 typedef struct {
2521         guint32 id;
2522         guint32 offset;
2523         GSList *children;
2524         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
2525 } ResTreeNode;
2526
2527 static int
2528 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
2529 {
2530         ResTreeNode *t1 = (ResTreeNode*)a;
2531         ResTreeNode *t2 = (ResTreeNode*)b;
2532
2533         return t1->id - t2->id;
2534 }
2535
2536 /*
2537  * resource_tree_create:
2538  *
2539  *  Organize the resources into a resource tree.
2540  */
2541 static ResTreeNode *
2542 resource_tree_create (MonoArray *win32_resources)
2543 {
2544         ResTreeNode *tree, *res_node, *type_node, *lang_node;
2545         GSList *l;
2546         int i;
2547
2548         tree = g_new0 (ResTreeNode, 1);
2549         
2550         for (i = 0; i < mono_array_length (win32_resources); ++i) {
2551                 MonoReflectionWin32Resource *win32_res =
2552                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
2553
2554                 /* Create node */
2555
2556                 /* FIXME: BUG: this stores managed references in unmanaged memory */
2557                 lang_node = g_new0 (ResTreeNode, 1);
2558                 lang_node->id = win32_res->lang_id;
2559                 lang_node->win32_res = win32_res;
2560
2561                 /* Create type node if neccesary */
2562                 type_node = NULL;
2563                 for (l = tree->children; l; l = l->next)
2564                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
2565                                 type_node = (ResTreeNode*)l->data;
2566                                 break;
2567                         }
2568
2569                 if (!type_node) {
2570                         type_node = g_new0 (ResTreeNode, 1);
2571                         type_node->id = win32_res->res_type;
2572
2573                         /* 
2574                          * The resource types have to be sorted otherwise
2575                          * Windows Explorer can't display the version information.
2576                          */
2577                         tree->children = g_slist_insert_sorted (tree->children, 
2578                                 type_node, resource_tree_compare_by_id);
2579                 }
2580
2581                 /* Create res node if neccesary */
2582                 res_node = NULL;
2583                 for (l = type_node->children; l; l = l->next)
2584                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
2585                                 res_node = (ResTreeNode*)l->data;
2586                                 break;
2587                         }
2588
2589                 if (!res_node) {
2590                         res_node = g_new0 (ResTreeNode, 1);
2591                         res_node->id = win32_res->res_id;
2592                         type_node->children = g_slist_append (type_node->children, res_node);
2593                 }
2594
2595                 res_node->children = g_slist_append (res_node->children, lang_node);
2596         }
2597
2598         return tree;
2599 }
2600
2601 /*
2602  * resource_tree_encode:
2603  * 
2604  *   Encode the resource tree into the format used in the PE file.
2605  */
2606 static void
2607 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
2608 {
2609         char *entries;
2610         MonoPEResourceDir dir;
2611         MonoPEResourceDirEntry dir_entry;
2612         MonoPEResourceDataEntry data_entry;
2613         GSList *l;
2614         guint32 res_id_entries;
2615
2616         /*
2617          * For the format of the resource directory, see the article
2618          * "An In-Depth Look into the Win32 Portable Executable File Format" by
2619          * Matt Pietrek
2620          */
2621
2622         memset (&dir, 0, sizeof (dir));
2623         memset (&dir_entry, 0, sizeof (dir_entry));
2624         memset (&data_entry, 0, sizeof (data_entry));
2625
2626         g_assert (sizeof (dir) == 16);
2627         g_assert (sizeof (dir_entry) == 8);
2628         g_assert (sizeof (data_entry) == 16);
2629
2630         node->offset = p - begin;
2631
2632         /* IMAGE_RESOURCE_DIRECTORY */
2633         res_id_entries = g_slist_length (node->children);
2634         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
2635
2636         memcpy (p, &dir, sizeof (dir));
2637         p += sizeof (dir);
2638
2639         /* Reserve space for entries */
2640         entries = p;
2641         p += sizeof (dir_entry) * res_id_entries;
2642
2643         /* Write children */
2644         for (l = node->children; l; l = l->next) {
2645                 ResTreeNode *child = (ResTreeNode*)l->data;
2646
2647                 if (child->win32_res) {
2648                         guint32 size;
2649
2650                         child->offset = p - begin;
2651
2652                         /* IMAGE_RESOURCE_DATA_ENTRY */
2653                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
2654                         size = mono_array_length (child->win32_res->res_data);
2655                         data_entry.rde_size = GUINT32_TO_LE (size);
2656
2657                         memcpy (p, &data_entry, sizeof (data_entry));
2658                         p += sizeof (data_entry);
2659
2660                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
2661                         p += size;
2662                 } else {
2663                         resource_tree_encode (child, begin, p, &p);
2664                 }
2665         }
2666
2667         /* IMAGE_RESOURCE_ENTRY */
2668         for (l = node->children; l; l = l->next) {
2669                 ResTreeNode *child = (ResTreeNode*)l->data;
2670
2671                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
2672                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
2673
2674                 memcpy (entries, &dir_entry, sizeof (dir_entry));
2675                 entries += sizeof (dir_entry);
2676         }
2677
2678         *endbuf = p;
2679 }
2680
2681 static void
2682 resource_tree_free (ResTreeNode * node)
2683 {
2684         GSList * list;
2685         for (list = node->children; list; list = list->next)
2686                 resource_tree_free ((ResTreeNode*)list->data);
2687         g_slist_free(node->children);
2688         g_free (node);
2689 }
2690
2691 static void
2692 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
2693 {
2694         char *buf;
2695         char *p;
2696         guint32 size, i;
2697         MonoReflectionWin32Resource *win32_res;
2698         ResTreeNode *tree;
2699
2700         if (!assemblyb->win32_resources)
2701                 return;
2702
2703         /*
2704          * Resources are stored in a three level tree inside the PE file.
2705          * - level one contains a node for each type of resource
2706          * - level two contains a node for each resource
2707          * - level three contains a node for each instance of a resource for a
2708          *   specific language.
2709          */
2710
2711         tree = resource_tree_create (assemblyb->win32_resources);
2712
2713         /* Estimate the size of the encoded tree */
2714         size = 0;
2715         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
2716                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
2717                 size += mono_array_length (win32_res->res_data);
2718         }
2719         /* Directory structure */
2720         size += mono_array_length (assemblyb->win32_resources) * 256;
2721         p = buf = (char *)g_malloc (size);
2722
2723         resource_tree_encode (tree, p, p, &p);
2724
2725         g_assert (p - buf <= size);
2726
2727         assembly->win32_res = (char *)g_malloc (p - buf);
2728         assembly->win32_res_size = p - buf;
2729         memcpy (assembly->win32_res, buf, p - buf);
2730
2731         g_free (buf);
2732         resource_tree_free (tree);
2733 }
2734
2735 static void
2736 fixup_resource_directory (char *res_section, char *p, guint32 rva)
2737 {
2738         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
2739         int i;
2740
2741         p += sizeof (MonoPEResourceDir);
2742         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
2743                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
2744                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
2745                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
2746                         fixup_resource_directory (res_section, child, rva);
2747                 } else {
2748                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
2749                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
2750                 }
2751
2752                 p += sizeof (MonoPEResourceDirEntry);
2753         }
2754 }
2755
2756 static void
2757 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
2758 {
2759         guint32 dummy;
2760         if (!mono_w32file_write (f, buffer, numbytes, &dummy))
2761                 g_error ("mono_w32file_write returned %d\n", mono_w32error_get_last ());
2762 }
2763
2764 /*
2765  * mono_image_create_pefile:
2766  * @mb: a module builder object
2767  * 
2768  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
2769  * assembly->pefile where it can be easily retrieved later in chunks.
2770  */
2771 gboolean
2772 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
2773 {
2774         MonoMSDOSHeader *msdos;
2775         MonoDotNetHeader *header;
2776         MonoSectionTable *section;
2777         MonoCLIHeader *cli_header;
2778         guint32 size, image_size, virtual_base, text_offset;
2779         guint32 header_start, section_start, file_offset, virtual_offset;
2780         MonoDynamicImage *assembly;
2781         MonoReflectionAssemblyBuilder *assemblyb;
2782         MonoDynamicStream pefile_stream = {0};
2783         MonoDynamicStream *pefile = &pefile_stream;
2784         int i, nsections;
2785         guint32 *rva, value;
2786         guchar *p;
2787         static const unsigned char msheader[] = {
2788                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
2789                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2790                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2791                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
2792                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
2793                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
2794                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
2795                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2796         };
2797
2798         error_init (error);
2799
2800         assemblyb = mb->assemblyb;
2801
2802         mono_reflection_dynimage_basic_init (assemblyb);
2803         assembly = mb->dynamic_image;
2804
2805         assembly->pe_kind = assemblyb->pe_kind;
2806         assembly->machine = assemblyb->machine;
2807         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
2808         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
2809         
2810         if (!mono_image_build_metadata (mb, error))
2811                 return FALSE;
2812         
2813
2814         if (mb->is_main && assemblyb->resources) {
2815                 int len = mono_array_length (assemblyb->resources);
2816                 for (i = 0; i < len; ++i) {
2817                         if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i), error))
2818                                 return FALSE;
2819                 }
2820         }
2821
2822         if (mb->resources) {
2823                 int len = mono_array_length (mb->resources);
2824                 for (i = 0; i < len; ++i) {
2825                         if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i), error))
2826                                 return FALSE;
2827                 }
2828         }
2829
2830         if (!build_compressed_metadata (assembly, error))
2831                 return FALSE;
2832
2833         if (mb->is_main)
2834                 assembly_add_win32_resources (assembly, assemblyb);
2835
2836         nsections = calc_section_size (assembly);
2837         
2838         /* The DOS header and stub */
2839         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
2840         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
2841
2842         /* the dotnet header */
2843         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
2844
2845         /* the section tables */
2846         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
2847
2848         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
2849         virtual_offset = VIRT_ALIGN;
2850         image_size = 0;
2851
2852         for (i = 0; i < MONO_SECTION_MAX; ++i) {
2853                 if (!assembly->sections [i].size)
2854                         continue;
2855                 /* align offsets */
2856                 file_offset += FILE_ALIGN - 1;
2857                 file_offset &= ~(FILE_ALIGN - 1);
2858                 virtual_offset += VIRT_ALIGN - 1;
2859                 virtual_offset &= ~(VIRT_ALIGN - 1);
2860
2861                 assembly->sections [i].offset = file_offset;
2862                 assembly->sections [i].rva = virtual_offset;
2863
2864                 file_offset += assembly->sections [i].size;
2865                 virtual_offset += assembly->sections [i].size;
2866                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
2867         }
2868
2869         file_offset += FILE_ALIGN - 1;
2870         file_offset &= ~(FILE_ALIGN - 1);
2871
2872         image_size += section_start + sizeof (MonoSectionTable) * nsections;
2873
2874         /* back-patch info */
2875         msdos = (MonoMSDOSHeader*)pefile->data;
2876         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
2877
2878         header = (MonoDotNetHeader*)(pefile->data + header_start);
2879         header->pesig [0] = 'P';
2880         header->pesig [1] = 'E';
2881         
2882         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
2883         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
2884         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
2885         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
2886         if (assemblyb->pekind == 1) {
2887                 /* it's a dll */
2888                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
2889         } else {
2890                 /* it's an exe */
2891                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
2892         }
2893
2894         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
2895
2896         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
2897         header->pe.pe_major = 6;
2898         header->pe.pe_minor = 0;
2899         size = assembly->sections [MONO_SECTION_TEXT].size;
2900         size += FILE_ALIGN - 1;
2901         size &= ~(FILE_ALIGN - 1);
2902         header->pe.pe_code_size = GUINT32_FROM_LE(size);
2903         size = assembly->sections [MONO_SECTION_RSRC].size;
2904         size += FILE_ALIGN - 1;
2905         size &= ~(FILE_ALIGN - 1);
2906         header->pe.pe_data_size = GUINT32_FROM_LE(size);
2907         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
2908         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
2909         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2910         /* pe_rva_entry_point always at the beginning of the text section */
2911         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
2912
2913         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
2914         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
2915         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
2916         header->nt.pe_os_major = GUINT16_FROM_LE (4);
2917         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
2918         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
2919         size = section_start;
2920         size += FILE_ALIGN - 1;
2921         size &= ~(FILE_ALIGN - 1);
2922         header->nt.pe_header_size = GUINT32_FROM_LE (size);
2923         size = image_size;
2924         size += VIRT_ALIGN - 1;
2925         size &= ~(VIRT_ALIGN - 1);
2926         header->nt.pe_image_size = GUINT32_FROM_LE (size);
2927
2928         /*
2929         // Translate the PEFileKind value to the value expected by the Windows loader
2930         */
2931         {
2932                 short kind;
2933
2934                 /*
2935                 // PEFileKinds.Dll == 1
2936                 // PEFileKinds.ConsoleApplication == 2
2937                 // PEFileKinds.WindowApplication == 3
2938                 //
2939                 // need to get:
2940                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
2941                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
2942                 */
2943                 if (assemblyb->pekind == 3)
2944                         kind = 2;
2945                 else
2946                         kind = 3;
2947                 
2948                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
2949         }    
2950         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
2951         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
2952         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
2953         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
2954         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
2955         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
2956
2957         /* fill data directory entries */
2958
2959         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
2960         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
2961
2962         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
2963         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
2964
2965         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
2966         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
2967         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
2968         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2969         /* patch entrypoint name */
2970         if (assemblyb->pekind == 1)
2971                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
2972         else
2973                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
2974         /* patch imported function RVA name */
2975         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
2976         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
2977
2978         /* the import table */
2979         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
2980         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
2981         /* patch imported dll RVA name and other entries in the dir */
2982         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
2983         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
2984         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
2985         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
2986         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
2987         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
2988
2989         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
2990         value = (assembly->text_rva + assembly->imp_names_offset);
2991         *p++ = (value) & 0xff;
2992         *p++ = (value >> 8) & (0xff);
2993         *p++ = (value >> 16) & (0xff);
2994         *p++ = (value >> 24) & (0xff);
2995
2996         /* the CLI header info */
2997         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
2998         cli_header->ch_size = GUINT32_FROM_LE (72);
2999         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
3000         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
3001         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
3002         if (assemblyb->entry_point) {
3003                 guint32 table_idx = 0;
3004                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
3005                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
3006                         table_idx = methodb->table_idx;
3007                 } else {
3008                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
3009                 }
3010                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
3011         } else {
3012                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
3013         }
3014         /* The embedded managed resources */
3015         text_offset = assembly->text_rva + assembly->code.index;
3016         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
3017         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
3018         text_offset += assembly->resources.index;
3019         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
3020         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
3021         text_offset += assembly->meta_size;
3022         if (assembly->strong_name_size) {
3023                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
3024                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
3025                 text_offset += assembly->strong_name_size;
3026         }
3027
3028         /* write the section tables and section content */
3029         section = (MonoSectionTable*)(pefile->data + section_start);
3030         for (i = 0; i < MONO_SECTION_MAX; ++i) {
3031                 static const char section_names [][7] = {
3032                         ".text", ".rsrc", ".reloc"
3033                 };
3034                 if (!assembly->sections [i].size)
3035                         continue;
3036                 strcpy (section->st_name, section_names [i]);
3037                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
3038                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
3039                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
3040                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
3041                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
3042                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
3043                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
3044                 section ++;
3045         }
3046         
3047         checked_write_file (file, pefile->data, pefile->index);
3048         
3049         mono_dynamic_stream_reset (pefile);
3050         
3051         for (i = 0; i < MONO_SECTION_MAX; ++i) {
3052                 if (!assembly->sections [i].size)
3053                         continue;
3054                 
3055                 if (mono_w32file_seek (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
3056                         g_error ("mono_w32file_seek returned %d\n", mono_w32error_get_last ());
3057                 
3058                 switch (i) {
3059                 case MONO_SECTION_TEXT:
3060                         /* patch entry point */
3061                         p = (guchar*)(assembly->code.data + 2);
3062                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
3063                         *p++ = (value) & 0xff;
3064                         *p++ = (value >> 8) & 0xff;
3065                         *p++ = (value >> 16) & 0xff;
3066                         *p++ = (value >> 24) & 0xff;
3067                 
3068                         checked_write_file (file, assembly->code.data, assembly->code.index);
3069                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
3070                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
3071                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
3072                                 
3073
3074                         g_free (assembly->image.raw_metadata);
3075                         break;
3076                 case MONO_SECTION_RELOC: {
3077                         struct {
3078                                 guint32 page_rva;
3079                                 guint32 block_size;
3080                                 guint16 type_and_offset;
3081                                 guint16 term;
3082                         } reloc;
3083                         
3084                         g_assert (sizeof (reloc) == 12);
3085                         
3086                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
3087                         reloc.block_size = GUINT32_FROM_LE (12);
3088                         
3089                         /* 
3090                          * the entrypoint is always at the start of the text section 
3091                          * 3 is IMAGE_REL_BASED_HIGHLOW
3092                          * 2 is patch_size_rva - text_rva
3093                          */
3094                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
3095                         reloc.term = 0;
3096                         
3097                         checked_write_file (file, &reloc, sizeof (reloc));
3098                         
3099                         break;
3100                 }
3101                 case MONO_SECTION_RSRC:
3102                         if (assembly->win32_res) {
3103
3104                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
3105                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
3106                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
3107                         }
3108                         break;
3109                 default:
3110                         g_assert_not_reached ();
3111                 }
3112         }
3113         
3114         /* check that the file is properly padded */
3115         if (mono_w32file_seek (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
3116                 g_error ("mono_w32file_seek returned %d\n", mono_w32error_get_last ());
3117         if (! mono_w32file_truncate (file))
3118                 g_error ("mono_w32file_truncate returned %d\n", mono_w32error_get_last ());
3119         
3120         mono_dynamic_stream_reset (&assembly->code);
3121         mono_dynamic_stream_reset (&assembly->us);
3122         mono_dynamic_stream_reset (&assembly->blob);
3123         mono_dynamic_stream_reset (&assembly->guid);
3124         mono_dynamic_stream_reset (&assembly->sheap);
3125
3126         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
3127         g_hash_table_destroy (assembly->blob_cache);
3128         assembly->blob_cache = NULL;
3129
3130         return TRUE;
3131 }
3132
3133 #else /* DISABLE_REFLECTION_EMIT_SAVE */
3134
3135 gboolean
3136 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
3137 {
3138         g_assert_not_reached ();
3139 }
3140
3141 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
3142