483ca68db303f8490158bb6a379b967b9e2889b3
[mono.git] / mcs / class / Mono.Cecil / 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                         return m_typeDefs [rid - 1];
127                 }
128
129                 public TypeReference GetTypeRefAt (uint rid)
130                 {
131                         return m_typeRefs [rid - 1];
132                 }
133
134                 public TypeReference GetTypeSpecAt (uint rid, GenericContext context)
135                 {
136                         int index = (int) rid - 1;
137                         TypeReference tspec = m_typeSpecs [index];
138                         if (tspec != null)
139                                 return tspec;
140
141                         TypeSpecTable tsTable = m_tableReader.GetTypeSpecTable ();
142                         TypeSpecRow tsRow = tsTable [index];
143                         TypeSpec ts = m_sigReader.GetTypeSpec (tsRow.Signature);
144                         tspec = GetTypeRefFromSig (ts.Type, context);
145                         tspec.MetadataToken = MetadataToken.FromMetadataRow (TokenType.TypeSpec, index);
146                         m_typeSpecs [index] = tspec;
147
148                         return tspec;
149                 }
150
151                 public FieldDefinition GetFieldDefAt (uint rid)
152                 {
153                         return m_fields [rid - 1];
154                 }
155
156                 public MethodDefinition GetMethodDefAt (uint rid)
157                 {
158                         return m_meths [rid - 1];
159                 }
160
161                 protected bool IsDeleted (IMemberDefinition member)
162                 {
163                         if (!m_checkDeleted)
164                                 return false;
165
166                         if (!member.IsSpecialName || !member.IsRuntimeSpecialName)
167                                 return false;
168
169                         return member.Name.StartsWith (Constants.Deleted);
170                 }
171
172                 public MemberReference GetMemberRefAt (uint rid, GenericContext context)
173                 {
174                         int index = (int) rid - 1;
175                         MemberReference member = m_memberRefs [rid - 1];
176                         if (member != null)
177                                 return member;
178
179                         MemberRefTable mrTable = m_tableReader.GetMemberRefTable ();
180                         MemberRefRow mrefRow = mrTable [index];
181
182                         Signature sig = m_sigReader.GetMemberRefSig (mrefRow.Class.TokenType, mrefRow.Signature);
183                         switch (mrefRow.Class.TokenType) {
184                         case TokenType.TypeDef :
185                         case TokenType.TypeRef :
186                         case TokenType.TypeSpec :
187                                 TypeReference declaringType = GetTypeDefOrRef (mrefRow.Class, context);
188                                 GenericContext nc = context.Clone ();
189
190                                 if (declaringType is GenericInstanceType) {
191                                         TypeReference ct = declaringType;
192                                         while (ct is GenericInstanceType)
193                                                 ct = (ct as GenericInstanceType).ElementType;
194
195                                         nc.Type = ct;
196                                         nc.AllowCreation = ct.GetType () == typeof (TypeReference);
197                                 }
198
199                                 if (sig is FieldSig) {
200                                         FieldSig fs = sig as FieldSig;
201                                         TypeReference fieldType = GetTypeRefFromSig (fs.Type, nc);
202                                         if (fs.CustomMods.Length > 0)
203                                                 fieldType = GetModifierType (fs.CustomMods, fieldType);
204
205                                         member = new FieldReference (
206                                                 m_root.Streams.StringsHeap [mrefRow.Name],
207                                                 declaringType,
208                                                 fieldType);
209                                 } else {
210                                         string name = m_root.Streams.StringsHeap [mrefRow.Name];
211                                         MethodSig ms = (MethodSig) sig;
212
213                                         member = CreateMethodReferenceFromSig (ms, name, declaringType, nc);
214                                 }
215                                 break;
216                         case TokenType.Method :
217                                 // really not sure about this
218                                 MethodDefinition methdef = GetMethodDefAt (mrefRow.Class.RID);
219
220                                 member = CreateMethodReferenceFromSig ((MethodSig) sig, methdef.Name, methdef.DeclaringType, new GenericContext ());
221                                 break;
222                         case TokenType.ModuleRef :
223                                 break; // TODO, implement that, or not
224                         }
225
226                         member.MetadataToken = MetadataToken.FromMetadataRow (TokenType.MemberRef, index);
227                         m_module.MemberReferences.Add (member);
228                         m_memberRefs [index] = member;
229
230                         return member;
231                 }
232
233                 MethodReference CreateMethodReferenceFromSig (MethodSig ms, string name, TypeReference declaringType, GenericContext context)
234                 {
235                         MethodReference methref = new MethodReference (
236                                 name, ms.HasThis, ms.ExplicitThis, ms.MethCallConv);
237                         methref.DeclaringType = declaringType;
238
239                         if (ms is MethodDefSig) {
240                                 int arity = (ms as MethodDefSig).GenericParameterCount;
241                                 for (int i = 0; i < arity; i++)
242                                         methref.GenericParameters.Add (new GenericParameter (i, methref));
243                         }
244
245                         if (methref.GenericParameters.Count > 0)
246                                 context.Method = methref;
247
248                         methref.ReturnType = GetMethodReturnType (ms, context);
249
250                         methref.ReturnType.Method = methref;
251                         for (int j = 0; j < ms.ParamCount; j++) {
252                                 Param p = ms.Parameters [j];
253                                 ParameterDefinition pdef = BuildParameterDefinition (j, p, context);
254                                 pdef.Method = methref;
255                                 methref.Parameters.Add (pdef);
256                         }
257
258                         CreateSentinelIfNeeded (methref, ms);
259
260                         return methref;
261                 }
262
263                 public static void CreateSentinelIfNeeded (IMethodSignature meth, MethodSig signature)
264                 {
265                         MethodDefSig sig = signature as MethodDefSig;
266                         if (sig == null)
267                                 return;
268
269                         int sentinel = sig.Sentinel;
270
271                         if (sig.Sentinel < 0 || sig.Sentinel >= meth.Parameters.Count)
272                                 return;
273
274                         ParameterDefinition param = meth.Parameters [sentinel];
275                         param.ParameterType = new SentinelType (param.ParameterType);
276                 }
277
278                 public PropertyDefinition GetPropertyDefAt (uint rid)
279                 {
280                         return m_properties [rid - 1];
281                 }
282
283                 public EventDefinition GetEventDefAt (uint rid)
284                 {
285                         return m_events [rid - 1];
286                 }
287
288                 public ParameterDefinition GetParamDefAt (uint rid)
289                 {
290                         return m_parameters [rid - 1];
291                 }
292
293                 public GenericParameter GetGenericParameterAt (uint rid)
294                 {
295                         return m_genericParameters [rid - 1];
296                 }
297
298                 public GenericInstanceMethod GetMethodSpecAt (uint rid, GenericContext context)
299                 {
300                         int index = (int) rid - 1;
301                         GenericInstanceMethod gim = m_methodSpecs [index];
302                         if (gim != null)
303                                 return gim;
304
305                         MethodSpecTable msTable = m_tableReader.GetMethodSpecTable ();
306                         MethodSpecRow msRow = msTable [index];
307
308                         MethodSpec sig = m_sigReader.GetMethodSpec (msRow.Instantiation);
309
310                         MethodReference meth;
311                         if (msRow.Method.TokenType == TokenType.Method)
312                                 meth = GetMethodDefAt (msRow.Method.RID);
313                         else if (msRow.Method.TokenType == TokenType.MemberRef)
314                                 meth = (MethodReference) GetMemberRefAt (msRow.Method.RID, context);
315                         else
316                                 throw new ReflectionException ("Unknown method type for method spec");
317
318                         gim = new GenericInstanceMethod (meth);
319                         foreach (GenericArg arg in sig.Signature.Types)
320                                 gim.GenericArguments.Add (GetGenericArg (arg, context));
321
322                         m_methodSpecs [index] = gim;
323
324                         return gim;
325                 }
326
327                 public TypeReference GetTypeDefOrRef (MetadataToken token, GenericContext context)
328                 {
329                         if (token.RID == 0)
330                                 return null;
331
332                         switch (token.TokenType) {
333                         case TokenType.TypeDef :
334                                 return GetTypeDefAt (token.RID);
335                         case TokenType.TypeRef :
336                                 return GetTypeRefAt (token.RID);
337                         case TokenType.TypeSpec :
338                                 return GetTypeSpecAt (token.RID, context);
339                         default :
340                                 return null;
341                         }
342                 }
343
344                 public TypeReference SearchCoreType (string fullName)
345                 {
346                         if (m_isCorlib)
347                                 return m_module.Types [fullName];
348
349                         TypeReference coreType =  m_module.TypeReferences [fullName];
350                         if (coreType == null) {
351
352                                 string [] parts = fullName.Split ('.');
353                                 if (parts.Length != 2)
354                                         throw new ReflectionException ("Unvalid core type name");
355                                 coreType = new TypeReference (parts [1], parts [0], Corlib);
356                                 m_module.TypeReferences.Add (coreType);
357                         }
358                         if (!coreType.IsValueType) {
359                                 switch (coreType.FullName) {
360                                 case Constants.Boolean :
361                                 case Constants.Char :
362                                 case Constants.Single :
363                                 case Constants.Double :
364                                 case Constants.SByte :
365                                 case Constants.Byte :
366                                 case Constants.Int16 :
367                                 case Constants.UInt16 :
368                                 case Constants.Int32 :
369                                 case Constants.UInt32 :
370                                 case Constants.Int64 :
371                                 case Constants.UInt64 :
372                                 case Constants.IntPtr :
373                                 case Constants.UIntPtr :
374                                         coreType.IsValueType = true;
375                                         break;
376                                 }
377                         }
378                         return coreType;
379                 }
380
381                 public IMetadataTokenProvider LookupByToken (MetadataToken token)
382                 {
383                         switch (token.TokenType) {
384                         case TokenType.TypeDef :
385                                 return GetTypeDefAt (token.RID);
386                         case TokenType.TypeRef :
387                                 return GetTypeRefAt (token.RID);
388                         case TokenType.Method :
389                                 return GetMethodDefAt (token.RID);
390                         case TokenType.Field :
391                                 return GetFieldDefAt (token.RID);
392                         case TokenType.Event :
393                                 return GetEventDefAt (token.RID);
394                         case TokenType.Property :
395                                 return GetPropertyDefAt (token.RID);
396                         case TokenType.Param :
397                                 return GetParamDefAt (token.RID);
398                         default :
399                                 throw new NotSupportedException ("Lookup is not allowed on this kind of token");
400                         }
401                 }
402
403                 public CustomAttribute GetCustomAttribute (MethodReference ctor, byte [] data, bool resolve)
404                 {
405                         CustomAttrib sig = m_sigReader.GetCustomAttrib (data, ctor, resolve);
406                         return BuildCustomAttribute (ctor, sig);
407                 }
408
409                 public CustomAttribute GetCustomAttribute (MethodReference ctor, byte [] data)
410                 {
411                         return GetCustomAttribute (ctor, data, false);
412                 }
413
414                 public override void VisitModuleDefinition (ModuleDefinition mod)
415                 {
416                         VisitTypeDefinitionCollection (mod.Types);
417                 }
418
419                 public override void VisitTypeDefinitionCollection (TypeDefinitionCollection types)
420                 {
421                         // type def reading
422                         TypeDefTable typesTable = m_tableReader.GetTypeDefTable ();
423                         m_typeDefs = new TypeDefinition [typesTable.Rows.Count];
424                         for (int i = 0; i < typesTable.Rows.Count; i++) {
425                                 TypeDefRow type = typesTable [i];
426                                 TypeDefinition t = new TypeDefinition (
427                                         m_root.Streams.StringsHeap [type.Name],
428                                         m_root.Streams.StringsHeap [type.Namespace],
429                                         type.Flags);
430                                 t.MetadataToken = MetadataToken.FromMetadataRow (TokenType.TypeDef, i);
431
432                                 m_typeDefs [i] = t;
433                         }
434
435                         // nested types
436                         if (m_tHeap.HasTable (NestedClassTable.RId)) {
437                                 NestedClassTable nested = m_tableReader.GetNestedClassTable ();
438                                 for (int i = 0; i < nested.Rows.Count; i++) {
439                                         NestedClassRow row = nested [i];
440
441                                         TypeDefinition parent = GetTypeDefAt (row.EnclosingClass);
442                                         TypeDefinition child = GetTypeDefAt (row.NestedClass);
443
444                                         if (!IsDeleted (child))
445                                                 parent.NestedTypes.Add (child);
446                                 }
447                         }
448
449                         foreach (TypeDefinition type in m_typeDefs)
450                                 if (!IsDeleted (type))
451                                         types.Add (type);
452
453                         // type ref reading
454                         if (m_tHeap.HasTable (TypeRefTable.RId)) {
455                                 TypeRefTable typesRef = m_tableReader.GetTypeRefTable ();
456
457                                 m_typeRefs = new TypeReference [typesRef.Rows.Count];
458
459                                 for (int i = 0; i < typesRef.Rows.Count; i++)
460                                         AddTypeRef (typesRef, i);
461                         } else
462                                 m_typeRefs = new TypeReference [0];
463
464                         ReadTypeSpecs ();
465                         ReadMethodSpecs ();
466
467                         ReadMethods ();
468                         ReadGenericParameters ();
469
470                         // set base types
471                         for (int i = 0; i < typesTable.Rows.Count; i++) {
472                                 TypeDefRow type = typesTable [i];
473                                 TypeDefinition child = m_typeDefs [i];
474                                 child.BaseType = GetTypeDefOrRef (type.Extends, new GenericContext (child));
475                         }
476
477                         CompleteMethods ();
478                         ReadAllFields ();
479                         ReadMemberReferences ();
480                 }
481
482                 void AddTypeRef (TypeRefTable typesRef, int i)
483                 {
484                         // Check if index has been already added.
485                         if (m_typeRefs [i] != null)
486                                 return;
487
488                         TypeRefRow type = typesRef [i];
489                         IMetadataScope scope = null;
490                         TypeReference parent = null;
491
492                         if (type.ResolutionScope.RID != 0) {
493                                 int rid = (int) type.ResolutionScope.RID - 1;
494                                 switch (type.ResolutionScope.TokenType) {
495                                 case TokenType.AssemblyRef:
496                                         scope = m_module.AssemblyReferences [rid];
497                                         break;
498                                 case TokenType.ModuleRef:
499                                         scope = m_module.ModuleReferences [rid];
500                                         break;
501                                 case TokenType.Module:
502                                         scope = m_module.Assembly.Modules [rid];
503                                         break;
504                                 case TokenType.TypeRef:
505                                         AddTypeRef (typesRef, rid);
506                                         parent = GetTypeRefAt (type.ResolutionScope.RID);
507                                         scope = parent.Scope;
508                                         break;
509                                 }
510                         }
511
512                         TypeReference t = new TypeReference (
513                                 m_root.Streams.StringsHeap [type.Name],
514                                 m_root.Streams.StringsHeap [type.Namespace],
515                                 scope);
516                         t.MetadataToken = MetadataToken.FromMetadataRow (TokenType.TypeRef, i);
517
518                         if (parent != null)
519                                 t.DeclaringType = parent;
520
521                         m_typeRefs [i] = t;
522                         m_module.TypeReferences.Add (t);
523                 }
524
525                 void ReadTypeSpecs ()
526                 {
527                         if (!m_tHeap.HasTable (TypeSpecTable.RId))
528                                 return;
529
530                         TypeSpecTable tsTable = m_tableReader.GetTypeSpecTable ();
531                         m_typeSpecs = new TypeReference [tsTable.Rows.Count];
532                 }
533
534                 void ReadMethodSpecs ()
535                 {
536                         if (!m_tHeap.HasTable (MethodSpecTable.RId))
537                                 return;
538
539                         MethodSpecTable msTable = m_tableReader.GetMethodSpecTable ();
540                         m_methodSpecs = new GenericInstanceMethod [msTable.Rows.Count];
541                 }
542
543                 void ReadGenericParameters ()
544                 {
545                         if (!m_tHeap.HasTable (GenericParamTable.RId))
546                                 return;
547
548                         GenericParamTable gpTable = m_tableReader.GetGenericParamTable ();
549                         m_genericParameters = new GenericParameter [gpTable.Rows.Count];
550                         for (int i = 0; i < gpTable.Rows.Count; i++) {
551                                 GenericParamRow gpRow = gpTable [i];
552                                 IGenericParameterProvider owner;
553                                 if (gpRow.Owner.TokenType == TokenType.Method)
554                                         owner = GetMethodDefAt (gpRow.Owner.RID);
555                                 else if (gpRow.Owner.TokenType == TokenType.TypeDef)
556                                         owner = GetTypeDefAt (gpRow.Owner.RID);
557                                 else
558                                         throw new ReflectionException ("Unknown owner type for generic parameter");
559
560                                 GenericParameter gp = new GenericParameter (gpRow.Number, owner);
561                                 gp.Attributes = gpRow.Flags;
562                                 gp.Name = MetadataRoot.Streams.StringsHeap [gpRow.Name];
563                                 gp.MetadataToken = MetadataToken.FromMetadataRow (TokenType.GenericParam, i);
564
565                                 owner.GenericParameters.Add (gp);
566                                 m_genericParameters [i] = gp;
567                         }
568                 }
569
570                 void ReadAllFields ()
571                 {
572                         TypeDefTable tdefTable = m_tableReader.GetTypeDefTable ();
573
574                         if (!m_tHeap.HasTable(FieldTable.RId)) {
575                                 m_fields = new FieldDefinition [0];
576                                 return;
577                         }
578
579                         FieldTable fldTable = m_tableReader.GetFieldTable ();
580                         m_fields = new FieldDefinition [fldTable.Rows.Count];
581
582                         for (int i = 0; i < m_typeDefs.Length; i++) {
583                                 TypeDefinition dec = m_typeDefs [i];
584                                 GenericContext context = new GenericContext (dec);
585
586                                 int index = i, next;
587
588                                 if (index == tdefTable.Rows.Count - 1)
589                                         next = fldTable.Rows.Count + 1;
590                                 else
591                                         next = (int) (tdefTable [index + 1]).FieldList;
592
593                                 for (int j = (int) tdefTable [index].FieldList; j < next; j++) {
594                                         FieldRow frow = fldTable [j - 1];
595                                         FieldSig fsig = m_sigReader.GetFieldSig (frow.Signature);
596
597                                         FieldDefinition fdef = new FieldDefinition (
598                                                 m_root.Streams.StringsHeap [frow.Name],
599                                                 GetTypeRefFromSig (fsig.Type, context), frow.Flags);
600                                         fdef.MetadataToken = MetadataToken.FromMetadataRow (TokenType.Field, j - 1);
601
602                                         if (fsig.CustomMods.Length > 0)
603                                                 fdef.FieldType = GetModifierType (fsig.CustomMods, fdef.FieldType);
604
605                                         if (!IsDeleted (fdef))
606                                                 dec.Fields.Add (fdef);
607
608                                         m_fields [j - 1] = fdef;
609                                 }
610                         }
611                 }
612
613                 void ReadMethods ()
614                 {
615                         if (!m_tHeap.HasTable (MethodTable.RId)) {
616                                 m_meths = new MethodDefinition [0];
617                                 return;
618                         }
619
620                         MethodTable mTable = m_tableReader.GetMethodTable ();
621                         m_meths = new MethodDefinition [mTable.Rows.Count];
622                         for (int i = 0; i < mTable.Rows.Count; i++) {
623                                 MethodRow mRow = mTable [i];
624                                 MethodDefinition meth = new MethodDefinition (
625                                         m_root.Streams.StringsHeap [mRow.Name],
626                                         mRow.Flags);
627                                 meth.RVA = mRow.RVA;
628                                 meth.ImplAttributes = mRow.ImplFlags;
629
630                                 meth.MetadataToken = MetadataToken.FromMetadataRow (TokenType.Method, i);
631
632                                 m_meths [i] = meth;
633                         }
634                 }
635
636                 void CompleteMethods ()
637                 {
638                         TypeDefTable tdefTable = m_tableReader.GetTypeDefTable ();
639
640                         if (!m_tHeap.HasTable (MethodTable.RId)) {
641                                 m_meths = new MethodDefinition [0];
642                                 return;
643                         }
644
645                         MethodTable methTable = m_tableReader.GetMethodTable ();
646                         ParamTable paramTable = m_tableReader.GetParamTable ();
647                         if (!m_tHeap.HasTable (ParamTable.RId))
648                                 m_parameters = new ParameterDefinition [0];
649                         else
650                                 m_parameters = new ParameterDefinition [paramTable.Rows.Count];
651
652                         for (int i = 0; i < m_typeDefs.Length; i++) {
653                                 TypeDefinition dec = m_typeDefs [i];
654
655                                 int index = i, next;
656
657                                 if (index == tdefTable.Rows.Count - 1)
658                                         next = methTable.Rows.Count + 1;
659                                 else
660                                         next = (int) (tdefTable [index + 1]).MethodList;
661
662                                 for (int j = (int) tdefTable [index].MethodList; j < next; j++) {
663                                         MethodRow methRow = methTable [j - 1];
664                                         MethodDefinition mdef = m_meths [j - 1];
665
666                                         if (!IsDeleted(mdef)) {
667                                                 if (mdef.IsConstructor)
668                                                         dec.Constructors.Add (mdef);
669                                                 else
670                                                         dec.Methods.Add (mdef);
671                                         }
672
673                                         GenericContext context = new GenericContext (mdef);
674
675                                         MethodDefSig msig = m_sigReader.GetMethodDefSig (methRow.Signature);
676                                         mdef.HasThis = msig.HasThis;
677                                         mdef.ExplicitThis = msig.ExplicitThis;
678                                         mdef.CallingConvention = msig.MethCallConv;
679
680                                         int prms;
681                                         if (j == methTable.Rows.Count)
682                                                 prms = m_parameters.Length + 1;
683                                         else
684                                                 prms = (int) (methTable [j]).ParamList;
685
686                                         ParameterDefinition retparam = null;
687
688                                         //TODO: optimize this
689                                         int start = (int) methRow.ParamList - 1;
690
691                                         if (paramTable != null && start < prms - 1) {
692
693                                                 ParamRow pRetRow = paramTable [start];
694
695                                                 if (pRetRow != null && pRetRow.Sequence == 0) { // ret type
696
697                                                         retparam = new ParameterDefinition (
698                                                                 m_root.Streams.StringsHeap [pRetRow.Name],
699                                                                 0,
700                                                                 pRetRow.Flags,
701                                                                 null);
702
703                                                         retparam.Method = mdef;
704                                                         m_parameters [start] = retparam;
705                                                         start++;
706                                                 }
707                                         }
708
709                                         for (int k = 0; k < msig.ParamCount; k++) {
710
711                                                 int pointer = start + k;
712
713                                                 ParamRow pRow = null;
714
715                                                 if (paramTable != null && pointer < prms - 1)
716                                                         pRow = paramTable [pointer];
717
718                                                 Param psig = msig.Parameters [k];
719
720                                                 ParameterDefinition pdef;
721                                                 if (pRow != null) {
722                                                         pdef = BuildParameterDefinition (
723                                                                 m_root.Streams.StringsHeap [pRow.Name],
724                                                                 pRow.Sequence, pRow.Flags, psig, context);
725                                                         pdef.MetadataToken = MetadataToken.FromMetadataRow (TokenType.Param, pointer);
726                                                         m_parameters [pointer] = pdef;
727                                                 } else
728                                                         pdef = BuildParameterDefinition (k + 1, psig, context);
729
730                                                 pdef.Method = mdef;
731                                                 mdef.Parameters.Add (pdef);
732                                         }
733
734                                         mdef.ReturnType = GetMethodReturnType (msig, context);
735                                         MethodReturnType mrt = mdef.ReturnType;
736                                         mrt.Method = mdef;
737                                         if (retparam != null) {
738                                                 mrt.Parameter = retparam;
739                                                 mrt.Parameter.ParameterType = mrt.ReturnType;
740                                         }
741                                 }
742                         }
743
744                         uint eprid = CodeReader.GetRid ((int) m_reader.Image.CLIHeader.EntryPointToken);
745                         if (eprid > 0 && eprid <= m_meths.Length)
746                                 m_module.Assembly.EntryPoint = GetMethodDefAt (eprid);
747                 }
748
749                 void ReadMemberReferences ()
750                 {
751                         if (!m_tHeap.HasTable (MemberRefTable.RId))
752                                 return;
753
754                         MemberRefTable mrefTable = m_tableReader.GetMemberRefTable ();
755                         m_memberRefs = new MemberReference [mrefTable.Rows.Count];
756                 }
757
758                 public override void VisitExternTypeCollection (ExternTypeCollection externs)
759                 {
760                         ExternTypeCollection ext = externs;
761
762                         if (!m_tHeap.HasTable (ExportedTypeTable.RId))
763                                 return;
764
765                         ExportedTypeTable etTable = m_tableReader.GetExportedTypeTable ();
766                         TypeReference [] buffer = new TypeReference [etTable.Rows.Count];
767
768                         for (int i = 0; i < etTable.Rows.Count; i++) {
769                                 ExportedTypeRow etRow = etTable [i];
770                                 if (etRow.Implementation.TokenType != TokenType.File)
771                                         continue;
772
773                                 string name = m_root.Streams.StringsHeap [etRow.TypeName];
774                                 string ns = m_root.Streams.StringsHeap [etRow.TypeNamespace];
775                                 if (ns.Length == 0)
776                                         buffer [i] = m_module.TypeReferences [name];
777                                 else
778                                         buffer [i] = m_module.TypeReferences [string.Concat (ns, '.', name)];
779                         }
780
781                         for (int i = 0; i < etTable.Rows.Count; i++) {
782                                 ExportedTypeRow etRow = etTable [i];
783                                 if (etRow.Implementation.TokenType != TokenType.ExportedType)
784                                         continue;
785
786                                 TypeReference owner = buffer [etRow.Implementation.RID - 1];
787                                 string name = m_root.Streams.StringsHeap [etRow.TypeName];
788                                 buffer [i] = m_module.TypeReferences [string.Concat (owner.FullName, '/', name)];
789                         }
790
791                         for (int i = 0; i < buffer.Length; i++) {
792                                 TypeReference curs = buffer [i];
793                                 if (curs != null)
794                                         ext.Add (curs);
795                         }
796                 }
797
798                 static object GetFixedArgValue (CustomAttrib.FixedArg fa)
799                 {
800                         if (fa.SzArray) {
801                                 object [] vals = new object [fa.NumElem];
802                                 for (int j = 0; j < vals.Length; j++)
803                                         vals [j] = fa.Elems [j].Value;
804                                 return vals;
805                         } else
806                                 return fa.Elems [0].Value;
807                 }
808
809                 TypeReference GetFixedArgType (CustomAttrib.FixedArg fa)
810                 {
811                         if (fa.SzArray) {
812                                 if (fa.NumElem == 0)
813                                         return new ArrayType (SearchCoreType (Constants.Object));
814                                 else
815                                         return new ArrayType (fa.Elems [0].ElemType);
816                         } else
817                                 return fa.Elems [0].ElemType;
818                 }
819
820                 TypeReference GetNamedArgType (CustomAttrib.NamedArg na)
821                 {
822                         if (na.FieldOrPropType == ElementType.Boxed)
823                                 return SearchCoreType (Constants.Object);
824
825                         return GetFixedArgType (na.FixedArg);
826                 }
827
828                 protected CustomAttribute BuildCustomAttribute (MethodReference ctor, CustomAttrib sig)
829                 {
830                         CustomAttribute cattr = new CustomAttribute (ctor);
831
832                         foreach (CustomAttrib.FixedArg fa in sig.FixedArgs)
833                                 cattr.ConstructorParameters.Add (GetFixedArgValue (fa));
834
835                         foreach (CustomAttrib.NamedArg na in sig.NamedArgs) {
836                                 object value = GetFixedArgValue (na.FixedArg);
837                                 if (na.Field) {
838                                         cattr.Fields [na.FieldOrPropName] = value;
839                                         cattr.SetFieldType (na.FieldOrPropName, GetNamedArgType (na));
840                                 } else if (na.Property) {
841                                         cattr.Properties [na.FieldOrPropName] = value;
842                                         cattr.SetPropertyType (na.FieldOrPropName, GetNamedArgType (na));
843                                 } else
844                                         throw new ReflectionException ("Non valid named arg");
845                         }
846
847                         return cattr;
848                 }
849
850                 void CompleteParameter (ParameterDefinition parameter, Param signature, GenericContext context)
851                 {
852                         TypeReference paramType;
853
854                         if (signature.ByRef)
855                                 paramType = new ReferenceType (GetTypeRefFromSig (signature.Type, context));
856                         else if (signature.TypedByRef)
857                                 paramType = SearchCoreType (Constants.TypedReference);
858                         else
859                                 paramType = GetTypeRefFromSig (signature.Type, context);
860
861                         if (signature.CustomMods.Length > 0)
862                                 paramType = GetModifierType (signature.CustomMods, paramType);
863
864                         parameter.ParameterType = paramType;
865                 }
866
867                 public ParameterDefinition BuildParameterDefinition (int sequence, Param psig, GenericContext context)
868                 {
869                         ParameterDefinition parameter = new ParameterDefinition (null);
870                         parameter.Sequence = sequence;
871
872                         CompleteParameter (parameter, psig, context);
873
874                         return parameter;
875                 }
876
877                 public ParameterDefinition BuildParameterDefinition (string name, int sequence, ParameterAttributes attrs, Param psig, GenericContext context)
878                 {
879                         ParameterDefinition parameter = new ParameterDefinition (name, sequence, attrs, null);
880
881                         CompleteParameter (parameter, psig, context);
882
883                         return parameter;
884                 }
885
886                 protected SecurityDeclaration BuildSecurityDeclaration (DeclSecurityRow dsRow)
887                 {
888                         return BuildSecurityDeclaration (dsRow.Action, m_root.Streams.BlobHeap.Read (dsRow.PermissionSet));
889                 }
890
891                 public SecurityDeclaration BuildSecurityDeclaration (SecurityAction action, byte [] permset)
892                 {
893                         if (m_secReader == null)
894                                 m_secReader = new SecurityDeclarationReader (m_root, this);
895
896                         return m_secReader.FromByteArray (action, permset);
897                 }
898
899                 protected MarshalSpec BuildMarshalDesc (MarshalSig ms, IHasMarshalSpec container)
900                 {
901                         if (ms.Spec is MarshalSig.Array) {
902                                 ArrayMarshalSpec amd = new ArrayMarshalSpec (container);
903                                 MarshalSig.Array ar = (MarshalSig.Array) ms.Spec;
904                                 amd.ElemType = ar.ArrayElemType;
905                                 amd.NumElem = ar.NumElem;
906                                 amd.ParamNum = ar.ParamNum;
907                                 amd.ElemMult = ar.ElemMult;
908                                 return amd;
909                         } else if (ms.Spec is MarshalSig.CustomMarshaler) {
910                                 CustomMarshalerSpec cmd = new CustomMarshalerSpec (container);
911                                 MarshalSig.CustomMarshaler cmsig = (MarshalSig.CustomMarshaler) ms.Spec;
912                                 cmd.Guid = cmsig.Guid.Length > 0 ? new Guid (cmsig.Guid) : new Guid ();
913                                 cmd.UnmanagedType = cmsig.UnmanagedType;
914                                 cmd.ManagedType = cmsig.ManagedType;
915                                 cmd.Cookie = cmsig.Cookie;
916                                 return cmd;
917                         } else if (ms.Spec is MarshalSig.FixedArray) {
918                                 FixedArraySpec fad = new FixedArraySpec (container);
919                                 MarshalSig.FixedArray fasig = (MarshalSig.FixedArray) ms.Spec;
920                                 fad.ElemType = fasig.ArrayElemType;
921                                 fad.NumElem = fasig.NumElem;
922                                 return fad;
923                         } else if (ms.Spec is MarshalSig.FixedSysString) {
924                                 FixedSysStringSpec fssc = new FixedSysStringSpec (container);
925                                 fssc.Size = ((MarshalSig.FixedSysString) ms.Spec).Size;
926                                 return fssc;
927                         } else if (ms.Spec is MarshalSig.SafeArray) {
928                                 SafeArraySpec sad = new SafeArraySpec (container);
929                                 sad.ElemType = ((MarshalSig.SafeArray) ms.Spec).ArrayElemType;
930                                 return sad;
931                         } else {
932                                 return new MarshalSpec (ms.NativeInstrinsic, container);
933                         }
934                 }
935
936                 public TypeReference GetModifierType (CustomMod [] cmods, TypeReference type)
937                 {
938                         TypeReference ret = type;
939                         for (int i = cmods.Length - 1; i >= 0; i--) {
940                                 CustomMod cmod = cmods [i];
941                                 TypeReference modType;
942
943                                 if (cmod.TypeDefOrRef.TokenType == TokenType.TypeDef)
944                                         modType = GetTypeDefAt (cmod.TypeDefOrRef.RID);
945                                 else
946                                         modType = GetTypeRefAt (cmod.TypeDefOrRef.RID);
947
948                                 if (cmod.CMOD == CustomMod.CMODType.OPT)
949                                         ret = new ModifierOptional (ret, modType);
950                                 else if (cmod.CMOD == CustomMod.CMODType.REQD)
951                                         ret = new ModifierRequired (ret, modType);
952                         }
953                         return ret;
954                 }
955
956                 public MethodReturnType GetMethodReturnType (MethodSig msig, GenericContext context)
957                 {
958                         TypeReference retType;
959                         if (msig.RetType.Void)
960                                 retType = SearchCoreType (Constants.Void);
961                         else if (msig.RetType.ByRef)
962                                 retType = new ReferenceType (GetTypeRefFromSig (msig.RetType.Type, context));
963                         else if (msig.RetType.TypedByRef)
964                                 retType = SearchCoreType (Constants.TypedReference);
965                         else
966                                 retType = GetTypeRefFromSig (msig.RetType.Type, context);
967
968                         if (msig.RetType.CustomMods.Length > 0)
969                                 retType = GetModifierType (msig.RetType.CustomMods, retType);
970
971                         return new MethodReturnType (retType);
972                 }
973
974                 public TypeReference GetTypeRefFromSig (SigType t, GenericContext context)
975                 {
976                         switch (t.ElementType) {
977                         case ElementType.Class :
978                                 CLASS c = t as CLASS;
979                                 return GetTypeDefOrRef (c.Type, context);
980                         case ElementType.ValueType :
981                                 VALUETYPE vt = t as VALUETYPE;
982                                 TypeReference vtr = GetTypeDefOrRef (vt.Type, context);
983                                 vtr.IsValueType = true;
984                                 return vtr;
985                         case ElementType.String :
986                                 return SearchCoreType (Constants.String);
987                         case ElementType.Object :
988                                 return SearchCoreType (Constants.Object);
989                         case ElementType.Void :
990                                 return SearchCoreType (Constants.Void);
991                         case ElementType.Boolean :
992                                 return SearchCoreType (Constants.Boolean);
993                         case ElementType.Char :
994                                 return SearchCoreType (Constants.Char);
995                         case ElementType.I1 :
996                                 return SearchCoreType (Constants.SByte);
997                         case ElementType.U1 :
998                                 return SearchCoreType (Constants.Byte);
999                         case ElementType.I2 :
1000                                 return SearchCoreType (Constants.Int16);
1001                         case ElementType.U2 :
1002                                 return SearchCoreType (Constants.UInt16);
1003                         case ElementType.I4 :
1004                                 return SearchCoreType (Constants.Int32);
1005                         case ElementType.U4 :
1006                                 return SearchCoreType (Constants.UInt32);
1007                         case ElementType.I8 :
1008                                 return SearchCoreType (Constants.Int64);
1009                         case ElementType.U8 :
1010                                 return SearchCoreType (Constants.UInt64);
1011                         case ElementType.R4 :
1012                                 return SearchCoreType (Constants.Single);
1013                         case ElementType.R8 :
1014                                 return SearchCoreType (Constants.Double);
1015                         case ElementType.I :
1016                                 return SearchCoreType (Constants.IntPtr);
1017                         case ElementType.U :
1018                                 return SearchCoreType (Constants.UIntPtr);
1019                         case ElementType.TypedByRef :
1020                                 return SearchCoreType (Constants.TypedReference);
1021                         case ElementType.Array :
1022                                 ARRAY ary = t as ARRAY;
1023                                 return new ArrayType (GetTypeRefFromSig (ary.Type, context), ary.Shape);
1024                         case ElementType.SzArray :
1025                                 SZARRAY szary = t as SZARRAY;
1026                                 ArrayType at = new ArrayType (GetTypeRefFromSig (szary.Type, context));
1027                                 return at;
1028                         case ElementType.Ptr :
1029                                 PTR pointer = t as PTR;
1030                                 if (pointer.Void)
1031                                         return new PointerType (SearchCoreType (Constants.Void));
1032                                 return new PointerType (GetTypeRefFromSig (pointer.PtrType, context));
1033                         case ElementType.FnPtr :
1034                                 FNPTR funcptr = t as FNPTR;
1035                                 FunctionPointerType fnptr = new FunctionPointerType (funcptr.Method.HasThis, funcptr.Method.ExplicitThis,
1036                                         funcptr.Method.MethCallConv, GetMethodReturnType (funcptr.Method, context));
1037
1038                                 for (int i = 0; i < funcptr.Method.ParamCount; i++) {
1039                                         Param p = funcptr.Method.Parameters [i];
1040                                         fnptr.Parameters.Add (BuildParameterDefinition (i, p, context));
1041                                 }
1042
1043                                 CreateSentinelIfNeeded (fnptr, funcptr.Method);
1044
1045                                 return fnptr;
1046                         case ElementType.Var:
1047                                 VAR var = t as VAR;
1048                                 if (context.AllowCreation)
1049                                         CheckGenericParameters (context, var);
1050
1051                                 if (context.Type is GenericInstanceType)
1052                                         return (context.Type as GenericInstanceType).GenericArguments [var.Index];
1053                                 else
1054                                         return context.Type.GenericParameters [var.Index];
1055                         case ElementType.MVar:
1056                                 MVAR mvar = t as MVAR;
1057                                 if (context.Method is GenericInstanceMethod)
1058                                         return (context.Method as GenericInstanceMethod).GenericArguments [mvar.Index];
1059                                 else
1060                                         return context.Method.GenericParameters [mvar.Index];
1061                         case ElementType.GenericInst:
1062                                 GENERICINST ginst = t as GENERICINST;
1063                                 GenericInstanceType instance = new GenericInstanceType (GetTypeDefOrRef (ginst.Type, context));
1064                                 instance.IsValueType = ginst.ValueType;
1065
1066                                 for (int i = 0; i < ginst.Signature.Arity; i++)
1067                                         instance.GenericArguments.Add (GetGenericArg (
1068                                                 ginst.Signature.Types [i], context));
1069
1070                                 return instance;
1071                         default:
1072                                 break;
1073                         }
1074                         return null;
1075                 }
1076
1077                 TypeReference GetGenericArg (GenericArg arg, GenericContext context)
1078                 {
1079                         TypeReference type = GetTypeRefFromSig (arg.Type, context);
1080                         if (arg.CustomMods != null && arg.CustomMods.Length > 0)
1081                                 type = GetModifierType (arg.CustomMods, type);
1082                         return type;
1083                 }
1084
1085                 static void CheckGenericParameters (GenericContext context, VAR v)
1086                 {
1087                         for (int i = context.Type.GenericParameters.Count; i <= v.Index; i++)
1088                                 context.Type.GenericParameters.Add (new GenericParameter (i, context.Type));
1089                 }
1090
1091                 protected object GetConstant (uint pos, ElementType elemType)
1092                 {
1093                         byte [] constant = m_root.Streams.BlobHeap.Read (pos);
1094                         BinaryReader br = new BinaryReader (new MemoryStream (constant));
1095
1096                         switch (elemType) {
1097                         case ElementType.Boolean :
1098                                 return br.ReadByte () == 1;
1099                         case ElementType.Char :
1100                                 return (char) br.ReadUInt16 ();
1101                         case ElementType.I1 :
1102                                 return br.ReadSByte ();
1103                         case ElementType.I2 :
1104                                 return br.ReadInt16 ();
1105                         case ElementType.I4 :
1106                                 return br.ReadInt32 ();
1107                         case ElementType.I8 :
1108                                 return br.ReadInt64 ();
1109                         case ElementType.U1 :
1110                                 return br.ReadByte ();
1111                         case ElementType.U2 :
1112                                 return br.ReadUInt16 ();
1113                         case ElementType.U4 :
1114                                 return br.ReadUInt32 ();
1115                         case ElementType.U8 :
1116                                 return br.ReadUInt64 ();
1117                         case ElementType.R4 :
1118                                 return br.ReadSingle ();
1119                         case ElementType.R8 :
1120                                 return br.ReadDouble ();
1121                         case ElementType.String :
1122                                 byte [] bytes = br.ReadBytes (constant.Length);
1123                                 string str = Encoding.Unicode.GetString (bytes, 0, bytes.Length);
1124                                 return str;
1125                         case ElementType.Class :
1126                                 return null;
1127                         default :
1128                                 throw new ReflectionException ("Non valid element in constant table");
1129                         }
1130                 }
1131
1132                 protected void SetInitialValue (FieldDefinition field)
1133                 {
1134                         int size = 0;
1135                         TypeReference fieldType = field.FieldType;
1136                         switch (fieldType.FullName) {
1137                         case Constants.Byte:
1138                         case Constants.SByte:
1139                                 size = 1;
1140                                 break;
1141                         case Constants.Int16:
1142                         case Constants.UInt16:
1143                         case Constants.Char:
1144                                 size = 2;
1145                                 break;
1146                         case Constants.Int32:
1147                         case Constants.UInt32:
1148                         case Constants.Single:
1149                                 size = 4;
1150                                 break;
1151                         case Constants.Int64:
1152                         case Constants.UInt64:
1153                         case Constants.Double:
1154                                 size = 8;
1155                                 break;
1156                         default:
1157                                 fieldType = fieldType.GetOriginalType ();
1158
1159                                 TypeDefinition fieldTypeDef = fieldType as TypeDefinition;
1160
1161                                 if (fieldTypeDef != null)
1162                                         size = (int) fieldTypeDef.ClassSize;
1163                                 break;
1164                         }
1165
1166                         if (size > 0 && field.RVA != RVA.Zero) {
1167                                 BinaryReader br = m_reader.MetadataReader.GetDataReader (field.RVA);
1168                                 field.InitialValue = br == null ? new byte [size] : br.ReadBytes (size);
1169                         } else
1170                                 field.InitialValue = new byte [0];
1171                 }
1172         }
1173 }