Merge pull request #463 from strawd/concurrent-requests
[mono.git] / mcs / tools / cil-strip / Mono.Cecil / ReflectionReader.cs
1 //
2 // ReflectionReader.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // (C) 2005 - 2007 Jb Evain
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 namespace Mono.Cecil {
30
31         using System;
32         using System.IO;
33         using System.Text;
34
35         using Mono.Cecil.Binary;
36         using Mono.Cecil.Cil;
37         using Mono.Cecil.Metadata;
38         using Mono.Cecil.Signatures;
39
40         internal abstract class ReflectionReader : BaseReflectionReader {
41
42                 ModuleDefinition m_module;
43                 ImageReader m_reader;
44                 SecurityDeclarationReader m_secReader;
45                 protected MetadataTableReader m_tableReader;
46                 protected MetadataRoot m_root;
47                 protected TablesHeap m_tHeap;
48                 protected bool m_checkDeleted;
49
50                 protected TypeDefinition [] m_typeDefs;
51                 protected TypeReference [] m_typeRefs;
52                 protected TypeReference [] m_typeSpecs;
53                 protected MethodDefinition [] m_meths;
54                 protected FieldDefinition [] m_fields;
55                 protected EventDefinition [] m_events;
56                 protected PropertyDefinition [] m_properties;
57                 protected MemberReference [] m_memberRefs;
58                 protected ParameterDefinition [] m_parameters;
59                 protected GenericParameter [] m_genericParameters;
60                 protected GenericInstanceMethod [] m_methodSpecs;
61
62                 bool m_isCorlib;
63                 AssemblyNameReference m_corlib;
64
65                 protected SignatureReader m_sigReader;
66                 protected CodeReader m_codeReader;
67                 protected ISymbolReader m_symbolReader;
68
69                 internal AssemblyNameReference Corlib {
70                         get {
71                                 if (m_corlib != null)
72                                         return m_corlib;
73
74                                 foreach (AssemblyNameReference ar in m_module.AssemblyReferences) {
75                                         if (ar.Name == Constants.Corlib) {
76                                                 m_corlib = ar;
77                                                 return m_corlib;
78                                         }
79                                 }
80
81                                 return null;
82                         }
83                 }
84
85                 public ModuleDefinition Module {
86                         get { return m_module; }
87                 }
88
89                 public SignatureReader SigReader {
90                         get { return m_sigReader; }
91                 }
92
93                 public MetadataTableReader TableReader {
94                         get { return m_tableReader; }
95                 }
96
97                 public CodeReader Code {
98                         get { return m_codeReader; }
99                 }
100
101                 public ISymbolReader SymbolReader {
102                         get { return m_symbolReader; }
103                         set { m_symbolReader = value; }
104                 }
105
106                 public MetadataRoot MetadataRoot {
107                         get { return m_root; }
108                 }
109
110                 public ReflectionReader (ModuleDefinition module)
111                 {
112                         m_module = module;
113                         m_reader = m_module.ImageReader;
114                         m_root = m_module.Image.MetadataRoot;
115                         m_tHeap = m_root.Streams.TablesHeap;
116                         m_checkDeleted = (m_tHeap.HeapSizes & 0x80) != 0;
117                         if (m_reader != null)
118                                 m_tableReader = m_reader.MetadataReader.TableReader;
119                         m_codeReader = new CodeReader (this);
120                         m_sigReader = new SignatureReader (m_root, this);
121                         m_isCorlib = module.Assembly.Name.Name == Constants.Corlib;
122                 }
123
124                 public TypeDefinition GetTypeDefAt (uint rid)
125                 {
126                         if (rid > m_typeDefs.Length)
127                                 return null;
128
129                         return m_typeDefs [rid - 1];
130                 }
131
132                 public TypeReference GetTypeRefAt (uint rid)
133                 {
134                         if (rid > m_typeRefs.Length)
135                                 return null;
136
137                         return m_typeRefs [rid - 1];
138                 }
139
140                 public TypeReference GetTypeSpecAt (uint rid, GenericContext context)
141                 {
142                         if (rid > m_typeSpecs.Length)
143                                 return null;
144
145                         int index = (int) rid - 1;
146
147                         TypeSpecTable tsTable = m_tableReader.GetTypeSpecTable ();
148                         TypeSpecRow tsRow = tsTable [index];
149                         TypeSpec ts = m_sigReader.GetTypeSpec (tsRow.Signature);
150
151                         // don't cache context dependent generic stuff
152                         if (IsGenericTypeSpec (ts.Type.ElementType))
153                                 return CreateTypeSpecFromSig (ts, index, context);
154
155                         TypeReference tspec = m_typeSpecs [index];
156                         if (tspec != null)
157                                 return tspec;
158
159                         tspec = CreateTypeSpecFromSig (ts, index, context);
160                         m_typeSpecs [index] = tspec;
161
162                         return tspec;
163                 }
164
165                 static bool IsGenericTypeSpec (ElementType etype)
166                 {
167                         return etype == ElementType.GenericInst
168                                 || etype == ElementType.Var
169                                 || etype == ElementType.MVar;
170                 }
171
172                 TypeReference CreateTypeSpecFromSig (TypeSpec ts, int index, GenericContext context)
173                 {
174                         TypeReference tspec = GetTypeRefFromSig (ts.Type, context);
175                         tspec = GetModifierType (ts.CustomMods, tspec);
176                         tspec.MetadataToken = MetadataToken.FromMetadataRow (TokenType.TypeSpec, index);
177                         return tspec;
178                 }
179
180                 public FieldDefinition GetFieldDefAt (uint rid)
181                 {
182                         if (rid > m_fields.Length)
183                                 return null;
184
185                         return m_fields [rid - 1];
186                 }
187
188                 public MethodDefinition GetMethodDefAt (uint rid)
189                 {
190                         if (rid > m_meths.Length)
191                                 return null;
192
193                         return m_meths [rid - 1];
194                 }
195
196                 protected bool IsDeleted (IMemberDefinition member)
197                 {
198                         if (!m_checkDeleted)
199                                 return false;
200
201                         if (!member.IsSpecialName || !member.IsRuntimeSpecialName)
202                                 return false;
203
204                         return member.Name.StartsWith (Constants.Deleted);
205                 }
206
207                 public MemberReference GetMemberRefAt (uint rid, GenericContext context)
208                 {
209                         if (rid > m_memberRefs.Length)
210                                 return null;
211
212                         int index = (int) rid - 1;
213                         MemberReference member = m_memberRefs [index];
214                         if (member != null)
215                                 return member;
216
217                         MemberRefTable mrTable = m_tableReader.GetMemberRefTable ();
218                         MemberRefRow mrefRow = mrTable [index];
219
220                         Signature sig = m_sigReader.GetMemberRefSig (mrefRow.Class.TokenType, mrefRow.Signature);
221                         switch (mrefRow.Class.TokenType) {
222                         case TokenType.TypeDef :
223                         case TokenType.TypeRef :
224                         case TokenType.TypeSpec :
225                                 TypeReference declaringType = GetTypeDefOrRef (mrefRow.Class, context);
226                                 GenericContext nc = context.Clone ();
227
228                                 if (declaringType is GenericInstanceType) {
229                                         TypeReference ct = declaringType;
230                                         while (ct is GenericInstanceType)
231                                                 ct = (ct as GenericInstanceType).ElementType;
232
233                                         nc.Type = ct;
234                                 }
235
236                                 if (sig is FieldSig) {
237                                         FieldSig fs = sig as FieldSig;
238                                         TypeReference fieldType = GetTypeRefFromSig (fs.Type, nc);
239                                         fieldType = GetModifierType (fs.CustomMods, fieldType);
240
241                                         member = new FieldReference (
242                                                 m_root.Streams.StringsHeap [mrefRow.Name],
243                                                 declaringType,
244                                                 fieldType);
245                                 } else {
246                                         string name = m_root.Streams.StringsHeap [mrefRow.Name];
247                                         MethodSig ms = (MethodSig) sig;
248
249                                         member = CreateMethodReferenceFromSig (ms, name, declaringType, nc);
250                                 }
251                                 break;
252                         case TokenType.Method :
253                                 // really not sure about this
254                                 MethodDefinition methdef = GetMethodDefAt (mrefRow.Class.RID);
255
256                                 member = CreateMethodReferenceFromSig ((MethodSig) sig, methdef.Name, methdef.DeclaringType, new GenericContext ());
257                                 break;
258                         case TokenType.ModuleRef :
259                                 break; // TODO, implement that, or not
260                         }
261
262                         member.MetadataToken = MetadataToken.FromMetadataRow (TokenType.MemberRef, index);
263                         m_module.MemberReferences.Add (member);
264                         m_memberRefs [index] = member;
265
266                         return member;
267                 }
268
269                 MethodReference CreateMethodReferenceFromSig (MethodSig ms, string name, TypeReference declaringType, GenericContext context)
270                 {
271                         MethodReference methref = new MethodReference (
272                                 name, ms.HasThis, ms.ExplicitThis, ms.MethCallConv);
273                         methref.DeclaringType = declaringType;
274
275                         if (ms is MethodDefSig) {
276                                 int arity = (ms as MethodDefSig).GenericParameterCount;
277                                 for (int i = 0; i < arity; i++)
278                                         methref.GenericParameters.Add (new GenericParameter (i, methref));
279                         }
280
281                         if (methref.GenericParameters.Count > 0)
282                                 context.Method = methref;
283
284                         methref.ReturnType = GetMethodReturnType (ms, context);
285
286                         methref.ReturnType.Method = methref;
287                         for (int j = 0; j < ms.ParamCount; j++) {
288                                 Param p = ms.Parameters [j];
289                                 ParameterDefinition pdef = BuildParameterDefinition (j, p, context);
290                                 pdef.Method = methref;
291                                 methref.Parameters.Add (pdef);
292                         }
293
294                         CreateSentinelIfNeeded (methref, ms);
295
296                         return methref;
297                 }
298
299                 public static void CreateSentinelIfNeeded (IMethodSignature meth, MethodSig signature)
300                 {
301                         MethodDefSig sig = signature as MethodDefSig;
302                         if (sig == null)
303                                 return;
304
305                         int sentinel = sig.Sentinel;
306
307                         if (sig.Sentinel < 0 || sig.Sentinel >= meth.Parameters.Count)
308                                 return;
309
310                         ParameterDefinition param = meth.Parameters [sentinel];
311                         param.ParameterType = new SentinelType (param.ParameterType);
312                 }
313
314                 public PropertyDefinition GetPropertyDefAt (uint rid)
315                 {
316                         if (rid > m_properties.Length)
317                                 return null;
318
319                         return m_properties [rid - 1];
320                 }
321
322                 public EventDefinition GetEventDefAt (uint rid)
323                 {
324                         if (rid > m_events.Length)
325                                 return null;
326
327                         return m_events [rid - 1];
328                 }
329
330                 public ParameterDefinition GetParamDefAt (uint rid)
331                 {
332                         if (rid > m_parameters.Length)
333                                 return null;
334
335                         return m_parameters [rid - 1];
336                 }
337
338                 public GenericParameter GetGenericParameterAt (uint rid)
339                 {
340                         if (rid > m_genericParameters.Length)
341                                 return null;
342
343                         return m_genericParameters [rid - 1];
344                 }
345
346                 public GenericInstanceMethod GetMethodSpecAt (uint rid, GenericContext context)
347                 {
348                         if (rid > m_methodSpecs.Length)
349                                 return null;
350
351                         int index = (int) rid - 1;
352                         GenericInstanceMethod gim = m_methodSpecs [index];
353                         if (gim != null)
354                                 return gim;
355
356                         MethodSpecTable msTable = m_tableReader.GetMethodSpecTable ();
357                         MethodSpecRow msRow = msTable [index];
358
359                         MethodSpec sig = m_sigReader.GetMethodSpec (msRow.Instantiation);
360
361                         MethodReference meth;
362                         if (msRow.Method.TokenType == TokenType.Method)
363                                 meth = GetMethodDefAt (msRow.Method.RID);
364                         else if (msRow.Method.TokenType == TokenType.MemberRef)
365                                 meth = (MethodReference) GetMemberRefAt (msRow.Method.RID, context);
366                         else
367                                 throw new ReflectionException ("Unknown method type for method spec");
368
369                         gim = new GenericInstanceMethod (meth);
370                         context.CheckProvider (meth, sig.Signature.Arity);
371                         foreach (GenericArg arg in sig.Signature.Types)
372                                 gim.GenericArguments.Add (GetGenericArg (arg, context));
373
374                         m_methodSpecs [index] = gim;
375
376                         return gim;
377                 }
378
379                 public TypeReference GetTypeDefOrRef (MetadataToken token, GenericContext context)
380                 {
381                         if (token.RID == 0)
382                                 return null;
383
384                         switch (token.TokenType) {
385                         case TokenType.TypeDef :
386                                 return GetTypeDefAt (token.RID);
387                         case TokenType.TypeRef :
388                                 return GetTypeRefAt (token.RID);
389                         case TokenType.TypeSpec :
390                                 return GetTypeSpecAt (token.RID, context);
391                         default :
392                                 return null;
393                         }
394                 }
395
396                 public TypeReference SearchCoreType (string fullName)
397                 {
398                         if (m_isCorlib)
399                                 return m_module.Types [fullName];
400
401                         TypeReference coreType =  m_module.TypeReferences [fullName];
402                         if (coreType == null) {
403                                 string [] parts = fullName.Split ('.');
404                                 if (parts.Length != 2)
405                                         throw new ReflectionException ("Unvalid core type name");
406                                 coreType = new TypeReference (parts [1], parts [0], Corlib);
407                                 m_module.TypeReferences.Add (coreType);
408                         }
409                         if (!coreType.IsValueType) {
410                                 switch (coreType.FullName) {
411                                 case Constants.Boolean :
412                                 case Constants.Char :
413                                 case Constants.Single :
414                                 case Constants.Double :
415                                 case Constants.SByte :
416                                 case Constants.Byte :
417                                 case Constants.Int16 :
418                                 case Constants.UInt16 :
419                                 case Constants.Int32 :
420                                 case Constants.UInt32 :
421                                 case Constants.Int64 :
422                                 case Constants.UInt64 :
423                                 case Constants.IntPtr :
424                                 case Constants.UIntPtr :
425                                         coreType.IsValueType = true;
426                                         break;
427                                 }
428                         }
429                         return coreType;
430                 }
431
432                 public IMetadataTokenProvider LookupByToken (MetadataToken token)
433                 {
434                         switch (token.TokenType) {
435                         case TokenType.TypeDef :
436                                 return GetTypeDefAt (token.RID);
437                         case TokenType.TypeRef :
438                                 return GetTypeRefAt (token.RID);
439                         case TokenType.Method :
440                                 return GetMethodDefAt (token.RID);
441                         case TokenType.Field :
442                                 return GetFieldDefAt (token.RID);
443                         case TokenType.Event :
444                                 return GetEventDefAt (token.RID);
445                         case TokenType.Property :
446                                 return GetPropertyDefAt (token.RID);
447                         case TokenType.Param :
448                                 return GetParamDefAt (token.RID);
449                         default :
450                                 throw new NotSupportedException ("Lookup is not allowed on this kind of token");
451                         }
452                 }
453
454                 public CustomAttribute GetCustomAttribute (MethodReference ctor, byte [] data, bool resolve)
455                 {
456                         CustomAttrib sig = m_sigReader.GetCustomAttrib (data, ctor, resolve);
457                         return BuildCustomAttribute (ctor, data, sig);
458                 }
459
460                 public CustomAttribute GetCustomAttribute (MethodReference ctor, byte [] data)
461                 {
462                         return GetCustomAttribute (ctor, data, false);
463                 }
464
465                 public override void VisitModuleDefinition (ModuleDefinition mod)
466                 {
467                         VisitTypeDefinitionCollection (mod.Types);
468                 }
469
470                 public override void VisitTypeDefinitionCollection (TypeDefinitionCollection types)
471                 {
472                         // type def reading
473                         TypeDefTable typesTable = m_tableReader.GetTypeDefTable ();
474                         m_typeDefs = new TypeDefinition [typesTable.Rows.Count];
475                         for (int i = 0; i < typesTable.Rows.Count; i++) {
476                                 TypeDefRow type = typesTable [i];
477                                 TypeDefinition t = new TypeDefinition (
478                                         m_root.Streams.StringsHeap [type.Name],
479                                         m_root.Streams.StringsHeap [type.Namespace],
480                                         type.Flags);
481                                 t.MetadataToken = MetadataToken.FromMetadataRow (TokenType.TypeDef, i);
482
483                                 m_typeDefs [i] = t;
484                         }
485
486                         // nested types
487                         if (m_tHeap.HasTable (NestedClassTable.RId)) {
488                                 NestedClassTable nested = m_tableReader.GetNestedClassTable ();
489                                 for (int i = 0; i < nested.Rows.Count; i++) {
490                                         NestedClassRow row = nested [i];
491
492                                         TypeDefinition parent = GetTypeDefAt (row.EnclosingClass);
493                                         TypeDefinition child = GetTypeDefAt (row.NestedClass);
494
495                                         if (!IsDeleted (child))
496                                                 parent.NestedTypes.Add (child);
497                                 }
498                         }
499
500                         foreach (TypeDefinition type in m_typeDefs)
501                                 if (!IsDeleted (type))
502                                         types.Add (type);
503
504                         // type ref reading
505                         if (m_tHeap.HasTable (TypeRefTable.RId)) {
506                                 TypeRefTable typesRef = m_tableReader.GetTypeRefTable ();
507
508                                 m_typeRefs = new TypeReference [typesRef.Rows.Count];
509
510                                 for (int i = 0; i < typesRef.Rows.Count; i++)
511                                         AddTypeRef (typesRef, i);
512                         } else
513                                 m_typeRefs = new TypeReference [0];
514
515                         ReadTypeSpecs ();
516                         ReadMethodSpecs ();
517
518                         ReadMethods ();
519                         ReadGenericParameters ();
520
521                         // set base types
522                         for (int i = 0; i < typesTable.Rows.Count; i++) {
523                                 TypeDefRow type = typesTable [i];
524                                 TypeDefinition child = m_typeDefs [i];
525                                 child.BaseType = GetTypeDefOrRef (type.Extends, new GenericContext (child));
526                         }
527
528                         CompleteMethods ();
529                         ReadAllFields ();
530                         ReadMemberReferences ();
531                 }
532
533                 void AddTypeRef (TypeRefTable typesRef, int i)
534                 {
535                         if (i >= typesRef.Rows.Count)
536                                 return;
537
538                         // Check if index has been already added.
539                         if (m_typeRefs [i] != null)
540                                 return;
541
542                         TypeRefRow type = typesRef [i];
543                         IMetadataScope scope = null;
544                         TypeReference parent = null;
545
546                         if (type.ResolutionScope.RID != 0) {
547                                 int rid = (int) type.ResolutionScope.RID - 1;
548                                 switch (type.ResolutionScope.TokenType) {
549                                 case TokenType.AssemblyRef:
550                                         scope = m_module.AssemblyReferences [rid];
551                                         break;
552                                 case TokenType.ModuleRef:
553                                         scope = m_module.ModuleReferences [rid];
554                                         break;
555                                 case TokenType.Module:
556                                         scope = m_module.Assembly.Modules [rid];
557                                         break;
558                                 case TokenType.TypeRef:
559                                         AddTypeRef (typesRef, rid);
560                                         parent = GetTypeRefAt (type.ResolutionScope.RID);
561                                         if (parent != null)
562                                                 scope = parent.Scope;
563                                         break;
564                                 }
565                         }
566
567                         TypeReference t = new TypeReference (
568                                 m_root.Streams.StringsHeap [type.Name],
569                                 m_root.Streams.StringsHeap [type.Namespace],
570                                 scope);
571                         t.MetadataToken = MetadataToken.FromMetadataRow (TokenType.TypeRef, i);
572
573                         if (parent != null)
574                                 t.DeclaringType = parent;
575
576                         m_typeRefs [i] = t;
577                         m_module.TypeReferences.Add (t);
578                 }
579
580                 void ReadTypeSpecs ()
581                 {
582                         if (!m_tHeap.HasTable (TypeSpecTable.RId))
583                                 return;
584
585                         TypeSpecTable tsTable = m_tableReader.GetTypeSpecTable ();
586                         m_typeSpecs = new TypeReference [tsTable.Rows.Count];
587                 }
588
589                 void ReadMethodSpecs ()
590                 {
591                         if (!m_tHeap.HasTable (MethodSpecTable.RId))
592                                 return;
593
594                         MethodSpecTable msTable = m_tableReader.GetMethodSpecTable ();
595                         m_methodSpecs = new GenericInstanceMethod [msTable.Rows.Count];
596                 }
597
598                 void ReadGenericParameters ()
599                 {
600                         if (!m_tHeap.HasTable (GenericParamTable.RId))
601                                 return;
602
603                         GenericParamTable gpTable = m_tableReader.GetGenericParamTable ();
604                         m_genericParameters = new GenericParameter [gpTable.Rows.Count];
605                         for (int i = 0; i < gpTable.Rows.Count; i++) {
606                                 GenericParamRow gpRow = gpTable [i];
607                                 IGenericParameterProvider owner;
608                                 if (gpRow.Owner.TokenType == TokenType.Method)
609                                         owner = GetMethodDefAt (gpRow.Owner.RID);
610                                 else if (gpRow.Owner.TokenType == TokenType.TypeDef)
611                                         owner = GetTypeDefAt (gpRow.Owner.RID);
612                                 else
613                                         throw new ReflectionException ("Unknown owner type for generic parameter");
614
615                                 GenericParameter gp = new GenericParameter (gpRow.Number, owner);
616                                 gp.Attributes = gpRow.Flags;
617                                 gp.Name = MetadataRoot.Streams.StringsHeap [gpRow.Name];
618                                 gp.MetadataToken = MetadataToken.FromMetadataRow (TokenType.GenericParam, i);
619
620                                 owner.GenericParameters.Add (gp);
621                                 m_genericParameters [i] = gp;
622                         }
623                 }
624
625                 void ReadAllFields ()
626                 {
627                         TypeDefTable tdefTable = m_tableReader.GetTypeDefTable ();
628
629                         if (!m_tHeap.HasTable (FieldTable.RId)) {
630                                 m_fields = new FieldDefinition [0];
631                                 return;
632                         }
633
634                         FieldTable fldTable = m_tableReader.GetFieldTable ();
635                         m_fields = new FieldDefinition [fldTable.Rows.Count];
636
637                         for (int i = 0; i < m_typeDefs.Length; i++) {
638                                 TypeDefinition dec = m_typeDefs [i];
639                                 GenericContext context = new GenericContext (dec);
640
641                                 int index = i, next;
642
643                                 if (index == tdefTable.Rows.Count - 1)
644                                         next = fldTable.Rows.Count + 1;
645                                 else
646                                         next = (int) (tdefTable [index + 1]).FieldList;
647
648                                 for (int j = (int) tdefTable [index].FieldList; j < next; j++) {
649                                         FieldRow frow = fldTable [j - 1];
650                                         FieldSig fsig = m_sigReader.GetFieldSig (frow.Signature);
651
652                                         FieldDefinition fdef = new FieldDefinition (
653                                                 m_root.Streams.StringsHeap [frow.Name],
654                                                 GetTypeRefFromSig (fsig.Type, context), frow.Flags);
655                                         fdef.MetadataToken = MetadataToken.FromMetadataRow (TokenType.Field, j - 1);
656
657                                         if (fsig.CustomMods.Length > 0)
658                                                 fdef.FieldType = GetModifierType (fsig.CustomMods, fdef.FieldType);
659
660                                         if (!IsDeleted (fdef))
661                                                 dec.Fields.Add (fdef);
662
663                                         m_fields [j - 1] = fdef;
664                                 }
665                         }
666                 }
667
668                 void ReadMethods ()
669                 {
670                         if (!m_tHeap.HasTable (MethodTable.RId)) {
671                                 m_meths = new MethodDefinition [0];
672                                 return;
673                         }
674
675                         MethodTable mTable = m_tableReader.GetMethodTable ();
676                         m_meths = new MethodDefinition [mTable.Rows.Count];
677                         for (int i = 0; i < mTable.Rows.Count; i++) {
678                                 MethodRow mRow = mTable [i];
679                                 MethodDefinition meth = new MethodDefinition (
680                                         m_root.Streams.StringsHeap [mRow.Name],
681                                         mRow.Flags);
682                                 meth.RVA = mRow.RVA;
683                                 meth.ImplAttributes = mRow.ImplFlags;
684
685                                 meth.MetadataToken = MetadataToken.FromMetadataRow (TokenType.Method, i);
686
687                                 m_meths [i] = meth;
688                         }
689                 }
690
691                 void CompleteMethods ()
692                 {
693                         TypeDefTable tdefTable = m_tableReader.GetTypeDefTable ();
694
695                         if (!m_tHeap.HasTable (MethodTable.RId)) {
696                                 m_meths = new MethodDefinition [0];
697                                 return;
698                         }
699
700                         MethodTable methTable = m_tableReader.GetMethodTable ();
701                         ParamTable paramTable = m_tableReader.GetParamTable ();
702                         if (!m_tHeap.HasTable (ParamTable.RId))
703                                 m_parameters = new ParameterDefinition [0];
704                         else
705                                 m_parameters = new ParameterDefinition [paramTable.Rows.Count];
706
707                         for (int i = 0; i < m_typeDefs.Length; i++) {
708                                 TypeDefinition dec = m_typeDefs [i];
709
710                                 int index = i, next;
711
712                                 if (index == tdefTable.Rows.Count - 1)
713                                         next = methTable.Rows.Count + 1;
714                                 else
715                                         next = (int) (tdefTable [index + 1]).MethodList;
716
717                                 for (int j = (int) tdefTable [index].MethodList; j < next; j++) {
718                                         MethodRow methRow = methTable [j - 1];
719                                         MethodDefinition mdef = m_meths [j - 1];
720
721                                         if (!IsDeleted (mdef)) {
722                                                 if (mdef.IsConstructor)
723                                                         dec.Constructors.Add (mdef);
724                                                 else
725                                                         dec.Methods.Add (mdef);
726                                         }
727
728                                         GenericContext context = new GenericContext (mdef);
729
730                                         MethodDefSig msig = m_sigReader.GetMethodDefSig (methRow.Signature);
731                                         mdef.HasThis = msig.HasThis;
732                                         mdef.ExplicitThis = msig.ExplicitThis;
733                                         mdef.CallingConvention = msig.MethCallConv;
734
735                                         int prms;
736                                         if (j == methTable.Rows.Count)
737                                                 prms = m_parameters.Length + 1;
738                                         else
739                                                 prms = (int) (methTable [j]).ParamList;
740
741                                         ParameterDefinition retparam = null;
742
743                                         //TODO: optimize this
744                                         int start = (int) methRow.ParamList - 1;
745
746                                         if (paramTable != null && start < prms - 1) {
747
748                                                 ParamRow pRetRow = paramTable [start];
749
750                                                 if (pRetRow != null && pRetRow.Sequence == 0) { // ret type
751
752                                                         retparam = new ParameterDefinition (
753                                                                 m_root.Streams.StringsHeap [pRetRow.Name],
754                                                                 0,
755                                                                 pRetRow.Flags,
756                                                                 null);
757
758                                                         retparam.Method = mdef;
759                                                         m_parameters [start] = retparam;
760                                                         start++;
761                                                 }
762                                         }
763
764                                         for (int k = 0; k < msig.ParamCount; k++) {
765
766                                                 int pointer = start + k;
767
768                                                 ParamRow pRow = null;
769
770                                                 if (paramTable != null && pointer < prms - 1)
771                                                         pRow = paramTable [pointer];
772
773                                                 Param psig = msig.Parameters [k];
774
775                                                 ParameterDefinition pdef;
776                                                 if (pRow != null) {
777                                                         pdef = BuildParameterDefinition (
778                                                                 m_root.Streams.StringsHeap [pRow.Name],
779                                                                 pRow.Sequence, pRow.Flags, psig, context);
780                                                         pdef.MetadataToken = MetadataToken.FromMetadataRow (TokenType.Param, pointer);
781                                                         m_parameters [pointer] = pdef;
782                                                 } else
783                                                         pdef = BuildParameterDefinition (k + 1, psig, context);
784
785                                                 pdef.Method = mdef;
786                                                 mdef.Parameters.Add (pdef);
787                                         }
788
789                                         mdef.ReturnType = GetMethodReturnType (msig, context);
790                                         MethodReturnType mrt = mdef.ReturnType;
791                                         mrt.Method = mdef;
792                                         if (retparam != null) {
793                                                 mrt.Parameter = retparam;
794                                                 mrt.Parameter.ParameterType = mrt.ReturnType;
795                                         }
796                                 }
797                         }
798
799                         uint eprid = CodeReader.GetRid ((int) m_reader.Image.CLIHeader.EntryPointToken);
800                         if (eprid > 0 && eprid <= m_meths.Length)
801                                 m_module.Assembly.EntryPoint = GetMethodDefAt (eprid);
802                 }
803
804                 void ReadMemberReferences ()
805                 {
806                         if (!m_tHeap.HasTable (MemberRefTable.RId))
807                                 return;
808
809                         MemberRefTable mrefTable = m_tableReader.GetMemberRefTable ();
810                         m_memberRefs = new MemberReference [mrefTable.Rows.Count];
811                 }
812
813                 public override void VisitExternTypeCollection (ExternTypeCollection externs)
814                 {
815                         ExternTypeCollection ext = externs;
816
817                         if (!m_tHeap.HasTable (ExportedTypeTable.RId))
818                                 return;
819
820                         ExportedTypeTable etTable = m_tableReader.GetExportedTypeTable ();
821                         TypeReference [] buffer = new TypeReference [etTable.Rows.Count];
822
823                         for (int i = 0; i < etTable.Rows.Count; i++) {
824                                 ExportedTypeRow etRow = etTable [i];
825
826                                 buffer [i] = new TypeDefinition (
827                                         m_root.Streams.StringsHeap [etRow.TypeName],
828                                         m_root.Streams.StringsHeap [etRow.TypeNamespace],
829                                         etRow.Flags);
830                                 buffer [i].AttachToScope (GetExportedTypeScope (etRow.Implementation));
831                         }
832
833                         for (int i = 0; i < etTable.Rows.Count; i++) {
834                                 ExportedTypeRow etRow = etTable [i];
835                                 if (etRow.Implementation.TokenType != TokenType.ExportedType)
836                                         continue;
837
838                                 TypeReference exported = buffer [i];
839                                 TypeReference owner = buffer [etRow.Implementation.RID - 1];
840                                 exported.DeclaringType = owner;
841                                 exported.AttachToScope (owner.Scope);
842                         }
843
844                         for (int i = 0; i < buffer.Length; i++) {
845                                 TypeReference curs = buffer [i];
846                                 if (curs != null)
847                                         ext.Add (curs);
848                         }
849                 }
850
851                 IMetadataScope GetExportedTypeScope (MetadataToken scope)
852                 {
853                         int index = (int) scope.RID - 1;
854                         switch (scope.TokenType) {
855                         case TokenType.AssemblyRef:
856                                 return Module.AssemblyReferences [index];
857                         case TokenType.File:
858                                 return Module.ModuleReferences [index];
859                         case TokenType.ExportedType:
860                                 return null; // resolved later
861                         default:
862                                 throw new NotSupportedException ();
863                         }
864                 }
865
866                 static object GetFixedArgValue (CustomAttrib.FixedArg fa)
867                 {
868                         if (fa.SzArray) {
869                                 object [] vals = new object [fa.NumElem];
870                                 for (int j = 0; j < vals.Length; j++)
871                                         vals [j] = fa.Elems [j].Value;
872                                 return vals;
873                         } else
874                                 return fa.Elems [0].Value;
875                 }
876
877                 TypeReference GetFixedArgType (CustomAttrib.FixedArg fa)
878                 {
879                         if (fa.SzArray) {
880                                 if (fa.NumElem == 0)
881                                         return new ArrayType (SearchCoreType (Constants.Object));
882                                 else
883                                         return new ArrayType (fa.Elems [0].ElemType);
884                         } else
885                                 return fa.Elems [0].ElemType;
886                 }
887
888                 TypeReference GetNamedArgType (CustomAttrib.NamedArg na)
889                 {
890                         if (na.FieldOrPropType == ElementType.Boxed)
891                                 return SearchCoreType (Constants.Object);
892
893                         return GetFixedArgType (na.FixedArg);
894                 }
895
896                 protected CustomAttribute BuildCustomAttribute (MethodReference ctor, byte [] data, CustomAttrib sig)
897                 {
898                         CustomAttribute cattr = new CustomAttribute (ctor);
899                         if (!sig.Read) {
900                                 cattr.Resolved = false;
901                                 cattr.Blob = data;
902                                 return cattr;
903                         }
904
905                         foreach (CustomAttrib.FixedArg fa in sig.FixedArgs)
906                                 cattr.ConstructorParameters.Add (GetFixedArgValue (fa));
907
908                         foreach (CustomAttrib.NamedArg na in sig.NamedArgs) {
909                                 object value = GetFixedArgValue (na.FixedArg);
910                                 if (na.Field) {
911                                         cattr.Fields [na.FieldOrPropName] = value;
912                                         cattr.SetFieldType (na.FieldOrPropName, GetNamedArgType (na));
913                                 } else if (na.Property) {
914                                         cattr.Properties [na.FieldOrPropName] = value;
915                                         cattr.SetPropertyType (na.FieldOrPropName, GetNamedArgType (na));
916                                 } else
917                                         throw new ReflectionException ("Non valid named arg");
918                         }
919
920                         return cattr;
921                 }
922
923                 void CompleteParameter (ParameterDefinition parameter, Param signature, GenericContext context)
924                 {
925                         TypeReference paramType;
926
927                         if (signature.TypedByRef)
928                                 paramType = SearchCoreType (Constants.TypedReference);
929                         else
930                                 paramType = GetTypeRefFromSig (signature.Type, context);
931
932                         paramType = GetModifierType (signature.CustomMods, paramType);
933
934                         if (signature.ByRef)
935                                 paramType = new ReferenceType (paramType);
936
937                         parameter.ParameterType = paramType;
938                 }
939
940                 public ParameterDefinition BuildParameterDefinition (int sequence, Param psig, GenericContext context)
941                 {
942                         ParameterDefinition parameter = new ParameterDefinition (null);
943                         parameter.Sequence = sequence;
944
945                         CompleteParameter (parameter, psig, context);
946
947                         return parameter;
948                 }
949
950                 public ParameterDefinition BuildParameterDefinition (string name, int sequence, ParameterAttributes attrs, Param psig, GenericContext context)
951                 {
952                         ParameterDefinition parameter = new ParameterDefinition (name, sequence, attrs, null);
953
954                         CompleteParameter (parameter, psig, context);
955
956                         return parameter;
957                 }
958
959                 protected SecurityDeclaration BuildSecurityDeclaration (DeclSecurityRow dsRow)
960                 {
961                         return BuildSecurityDeclaration (dsRow.Action, m_root.Streams.BlobHeap.Read (dsRow.PermissionSet));
962                 }
963
964                 public SecurityDeclaration BuildSecurityDeclaration (SecurityAction action, byte [] permset)
965                 {
966                         if (m_secReader == null)
967                                 m_secReader = new SecurityDeclarationReader (m_root, this);
968
969                         return m_secReader.FromByteArray (action, permset);
970                 }
971
972                 protected MarshalSpec BuildMarshalDesc (MarshalSig ms, IHasMarshalSpec container)
973                 {
974                         if (ms.Spec is MarshalSig.Array) {
975                                 ArrayMarshalSpec amd = new ArrayMarshalSpec (container);
976                                 MarshalSig.Array ar = (MarshalSig.Array) ms.Spec;
977                                 amd.ElemType = ar.ArrayElemType;
978                                 amd.NumElem = ar.NumElem;
979                                 amd.ParamNum = ar.ParamNum;
980                                 amd.ElemMult = ar.ElemMult;
981                                 return amd;
982                         } else if (ms.Spec is MarshalSig.CustomMarshaler) {
983                                 CustomMarshalerSpec cmd = new CustomMarshalerSpec (container);
984                                 MarshalSig.CustomMarshaler cmsig = (MarshalSig.CustomMarshaler) ms.Spec;
985                                 cmd.Guid = cmsig.Guid.Length > 0 ? new Guid (cmsig.Guid) : new Guid ();
986                                 cmd.UnmanagedType = cmsig.UnmanagedType;
987                                 cmd.ManagedType = cmsig.ManagedType;
988                                 cmd.Cookie = cmsig.Cookie;
989                                 return cmd;
990                         } else if (ms.Spec is MarshalSig.FixedArray) {
991                                 FixedArraySpec fad = new FixedArraySpec (container);
992                                 MarshalSig.FixedArray fasig = (MarshalSig.FixedArray) ms.Spec;
993                                 fad.ElemType = fasig.ArrayElemType;
994                                 fad.NumElem = fasig.NumElem;
995                                 return fad;
996                         } else if (ms.Spec is MarshalSig.FixedSysString) {
997                                 FixedSysStringSpec fssc = new FixedSysStringSpec (container);
998                                 fssc.Size = ((MarshalSig.FixedSysString) ms.Spec).Size;
999                                 return fssc;
1000                         } else if (ms.Spec is MarshalSig.SafeArray) {
1001                                 SafeArraySpec sad = new SafeArraySpec (container);
1002                                 sad.ElemType = ((MarshalSig.SafeArray) ms.Spec).ArrayElemType;
1003                                 return sad;
1004                         } else {
1005                                 return new MarshalSpec (ms.NativeInstrinsic, container);
1006                         }
1007                 }
1008
1009                 public TypeReference GetModifierType (CustomMod [] cmods, TypeReference type)
1010                 {
1011                         if (cmods == null || cmods.Length == 0)
1012                                 return type;
1013
1014                         TypeReference ret = type;
1015                         for (int i = cmods.Length - 1; i >= 0; i--) {
1016                                 CustomMod cmod = cmods [i];
1017                                 TypeReference modType;
1018
1019                                 if (cmod.TypeDefOrRef.RID == 0)
1020                                         continue;
1021
1022                                 if (cmod.TypeDefOrRef.TokenType == TokenType.TypeDef)
1023                                         modType = GetTypeDefAt (cmod.TypeDefOrRef.RID);
1024                                 else
1025                                         modType = GetTypeRefAt (cmod.TypeDefOrRef.RID);
1026
1027                                 if (cmod.CMOD == CustomMod.CMODType.OPT)
1028                                         ret = new ModifierOptional (ret, modType);
1029                                 else if (cmod.CMOD == CustomMod.CMODType.REQD)
1030                                         ret = new ModifierRequired (ret, modType);
1031                         }
1032                         return ret;
1033                 }
1034
1035                 public MethodReturnType GetMethodReturnType (MethodSig msig, GenericContext context)
1036                 {
1037                         TypeReference retType;
1038                         if (msig.RetType.Void)
1039                                 retType = SearchCoreType (Constants.Void);
1040                         else if (msig.RetType.TypedByRef)
1041                                 retType = SearchCoreType (Constants.TypedReference);
1042                         else
1043                                 retType = GetTypeRefFromSig (msig.RetType.Type, context);
1044
1045                         retType = GetModifierType (msig.RetType.CustomMods, retType);
1046
1047                         if (msig.RetType.ByRef)
1048                                 retType = new ReferenceType (retType);
1049
1050                         return new MethodReturnType (retType);
1051                 }
1052
1053                 public TypeReference GetTypeRefFromSig (SigType t, GenericContext context)
1054                 {
1055                         switch (t.ElementType) {
1056                         case ElementType.Class :
1057                                 CLASS c = t as CLASS;
1058                                 return GetTypeDefOrRef (c.Type, context);
1059                         case ElementType.ValueType :
1060                                 VALUETYPE vt = t as VALUETYPE;
1061                                 TypeReference vtr = GetTypeDefOrRef (vt.Type, context);
1062                                 vtr.IsValueType = true;
1063                                 return vtr;
1064                         case ElementType.String :
1065                                 return SearchCoreType (Constants.String);
1066                         case ElementType.Object :
1067                                 return SearchCoreType (Constants.Object);
1068                         case ElementType.Void :
1069                                 return SearchCoreType (Constants.Void);
1070                         case ElementType.Boolean :
1071                                 return SearchCoreType (Constants.Boolean);
1072                         case ElementType.Char :
1073                                 return SearchCoreType (Constants.Char);
1074                         case ElementType.I1 :
1075                                 return SearchCoreType (Constants.SByte);
1076                         case ElementType.U1 :
1077                                 return SearchCoreType (Constants.Byte);
1078                         case ElementType.I2 :
1079                                 return SearchCoreType (Constants.Int16);
1080                         case ElementType.U2 :
1081                                 return SearchCoreType (Constants.UInt16);
1082                         case ElementType.I4 :
1083                                 return SearchCoreType (Constants.Int32);
1084                         case ElementType.U4 :
1085                                 return SearchCoreType (Constants.UInt32);
1086                         case ElementType.I8 :
1087                                 return SearchCoreType (Constants.Int64);
1088                         case ElementType.U8 :
1089                                 return SearchCoreType (Constants.UInt64);
1090                         case ElementType.R4 :
1091                                 return SearchCoreType (Constants.Single);
1092                         case ElementType.R8 :
1093                                 return SearchCoreType (Constants.Double);
1094                         case ElementType.I :
1095                                 return SearchCoreType (Constants.IntPtr);
1096                         case ElementType.U :
1097                                 return SearchCoreType (Constants.UIntPtr);
1098                         case ElementType.TypedByRef :
1099                                 return SearchCoreType (Constants.TypedReference);
1100                         case ElementType.Array :
1101                                 ARRAY ary = t as ARRAY;
1102                                 return new ArrayType (GetTypeRefFromSig (ary.Type, context), ary.Shape);
1103                         case ElementType.SzArray :
1104                                 SZARRAY szary = t as SZARRAY;
1105                                 ArrayType at = new ArrayType (GetTypeRefFromSig (szary.Type, context));
1106                                 return at;
1107                         case ElementType.Ptr :
1108                                 PTR pointer = t as PTR;
1109                                 if (pointer.Void)
1110                                         return new PointerType (SearchCoreType (Constants.Void));
1111                                 return new PointerType (GetTypeRefFromSig (pointer.PtrType, context));
1112                         case ElementType.FnPtr :
1113                                 FNPTR funcptr = t as FNPTR;
1114                                 FunctionPointerType fnptr = new FunctionPointerType (funcptr.Method.HasThis, funcptr.Method.ExplicitThis,
1115                                         funcptr.Method.MethCallConv, GetMethodReturnType (funcptr.Method, context));
1116
1117                                 for (int i = 0; i < funcptr.Method.ParamCount; i++) {
1118                                         Param p = funcptr.Method.Parameters [i];
1119                                         fnptr.Parameters.Add (BuildParameterDefinition (i, p, context));
1120                                 }
1121
1122                                 CreateSentinelIfNeeded (fnptr, funcptr.Method);
1123
1124                                 return fnptr;
1125                         case ElementType.Var:
1126                                 VAR var = t as VAR;
1127                                 context.CheckProvider (context.Type, var.Index + 1);
1128
1129                                 if (context.Type is GenericInstanceType)
1130                                         return (context.Type as GenericInstanceType).GenericArguments [var.Index];
1131                                 else
1132                                         return context.Type.GenericParameters [var.Index];
1133                         case ElementType.MVar:
1134                                 MVAR mvar = t as MVAR;
1135                                 context.CheckProvider (context.Method, mvar.Index + 1);
1136
1137                                 if (context.Method is GenericInstanceMethod)
1138                                         return (context.Method as GenericInstanceMethod).GenericArguments [mvar.Index];
1139                                 else
1140                                         return context.Method.GenericParameters [mvar.Index];
1141                         case ElementType.GenericInst:
1142                                 GENERICINST ginst = t as GENERICINST;
1143                                 GenericInstanceType instance = new GenericInstanceType (GetTypeDefOrRef (ginst.Type, context));
1144                                 instance.IsValueType = ginst.ValueType;
1145                                 context.CheckProvider (instance.GetOriginalType (), ginst.Signature.Arity);
1146
1147                                 for (int i = 0; i < ginst.Signature.Arity; i++)
1148                                         instance.GenericArguments.Add (GetGenericArg (
1149                                                 ginst.Signature.Types [i], context));
1150
1151                                 return instance;
1152                         default:
1153                                 break;
1154                         }
1155                         return null;
1156                 }
1157
1158                 TypeReference GetGenericArg (GenericArg arg, GenericContext context)
1159                 {
1160                         TypeReference type = GetTypeRefFromSig (arg.Type, context);
1161                         type = GetModifierType (arg.CustomMods, type);
1162                         return type;
1163                 }
1164
1165                 static bool IsOdd (int i)
1166                 {
1167                         return (i & 1) == 1;
1168                 }
1169
1170                 protected object GetConstant (uint pos, ElementType elemType)
1171                 {
1172                         if (elemType == ElementType.Class)
1173                                 return null;
1174
1175                         byte [] constant = m_root.Streams.BlobHeap.Read (pos);
1176
1177                         if (elemType == ElementType.String) {
1178                                 int length = constant.Length;
1179                                 if (IsOdd (length))
1180                                         length--;
1181
1182                                 return Encoding.Unicode.GetString (constant, 0, length);
1183                         }
1184
1185                         // One byte types can always be read using BitConverter. However it can't be used
1186                         // elsewhere since it behaves differently in Mono compared to CF on BE architectures
1187                         switch (elemType) {
1188                         case ElementType.Boolean :
1189                                 return BitConverter.ToBoolean (constant, 0);
1190                         case ElementType.I1 :
1191                                 return (sbyte) constant [0];
1192                         case ElementType.U1 :
1193                                 return (byte) constant [0];
1194                         case ElementType.Object: // illegal, but foundable
1195                                 return null;
1196                         default :
1197                                 if (BitConverter.IsLittleEndian)
1198                                         return GetConstantLittleEndian (elemType, constant);
1199                                 else
1200                                         return GetConstantBigEndian (elemType, constant);
1201                         }
1202                 }
1203
1204                 static object GetConstantLittleEndian (ElementType elemType, byte [] constant)
1205                 {
1206                         switch (elemType) {
1207                         case ElementType.Char :
1208                                 return BitConverter.ToChar (constant, 0);
1209                         case ElementType.I2 :
1210                                 return BitConverter.ToInt16 (constant, 0);
1211                         case ElementType.I4 :
1212                                 return BitConverter.ToInt32 (constant, 0);
1213                         case ElementType.I8 :
1214                                 return BitConverter.ToInt64 (constant, 0);
1215                         case ElementType.U2 :
1216                                 return BitConverter.ToUInt16 (constant, 0);
1217                         case ElementType.U4 :
1218                                 return BitConverter.ToUInt32 (constant, 0);
1219                         case ElementType.U8 :
1220                                 return BitConverter.ToUInt64 (constant, 0);
1221                         case ElementType.R4 :
1222                                 return BitConverter.ToSingle (constant, 0);
1223                         case ElementType.R8 :
1224                                 return BitConverter.ToDouble (constant, 0);
1225                         default:
1226                                 throw new ReflectionException ("Non valid element in constant table");
1227                         }
1228                 }
1229
1230                 static object GetConstantBigEndian (ElementType elemType, byte [] constant)
1231                 {
1232                         // BinaryReader always read it's data in LE format
1233                         // note: this could be further optimized (even without unsafe code)
1234                         BinaryReader br = new BinaryReader (new MemoryStream (constant));
1235                         switch (elemType) {
1236                         case ElementType.Char :
1237                                 return (char) br.ReadUInt16 ();
1238                         case ElementType.I2 :
1239                                 return br.ReadInt16 ();
1240                         case ElementType.I4 :
1241                                 return br.ReadInt32 ();
1242                         case ElementType.I8 :
1243                                 return br.ReadInt64 ();
1244                         case ElementType.U2 :
1245                                 return br.ReadUInt16 ();
1246                         case ElementType.U4 :
1247                                 return br.ReadUInt32 ();
1248                         case ElementType.U8 :
1249                                 return br.ReadUInt64 ();
1250                         case ElementType.R4 :
1251                                 return br.ReadSingle ();
1252                         case ElementType.R8 :
1253                                 return br.ReadDouble ();
1254                         default:
1255                                 throw new ReflectionException ("Non valid element in constant table");
1256                         }
1257                 }
1258
1259                 protected void SetInitialValue (FieldDefinition field)
1260                 {
1261                         int size = 0;
1262                         TypeReference fieldType = field.FieldType;
1263                         switch (fieldType.FullName) {
1264                         case Constants.Boolean:
1265                         case Constants.Byte:
1266                         case Constants.SByte:
1267                                 size = 1;
1268                                 break;
1269                         case Constants.Int16:
1270                         case Constants.UInt16:
1271                         case Constants.Char:
1272                                 size = 2;
1273                                 break;
1274                         case Constants.Int32:
1275                         case Constants.UInt32:
1276                         case Constants.Single:
1277                                 size = 4;
1278                                 break;
1279                         case Constants.Int64:
1280                         case Constants.UInt64:
1281                         case Constants.Double:
1282                                 size = 8;
1283                                 break;
1284                         default:
1285                                 fieldType = fieldType.GetOriginalType ();
1286
1287                                 TypeDefinition fieldTypeDef = fieldType as TypeDefinition;
1288
1289                                 if (fieldTypeDef != null)
1290                                         size = (int) fieldTypeDef.ClassSize;
1291                                 break;
1292                         }
1293
1294                         if (size > 0 && field.RVA != RVA.Zero) {
1295                                 byte [] data = new byte [size];
1296                                 Section sect = m_reader.Image.GetSectionAtVirtualAddress (field.RVA);
1297                                 if (sect != null)
1298                                         Buffer.BlockCopy (sect.Data, (int) (long) (field.RVA - sect.VirtualAddress), data, 0, size);
1299                                 field.InitialValue = data;
1300                         } else
1301                                 field.InitialValue = new byte [0];
1302                 }
1303         }
1304 }