5 // Jb Evain (jbevain@gmail.com)
7 // (C) 2005 - 2007 Jb Evain
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
29 namespace Mono.Cecil {
35 using Mono.Cecil.Binary;
37 using Mono.Cecil.Metadata;
38 using Mono.Cecil.Signatures;
40 internal abstract class ReflectionReader : BaseReflectionReader {
42 ModuleDefinition m_module;
44 SecurityDeclarationReader m_secReader;
45 protected MetadataTableReader m_tableReader;
46 protected MetadataRoot m_root;
47 protected TablesHeap m_tHeap;
48 protected bool m_checkDeleted;
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;
63 AssemblyNameReference m_corlib;
65 protected SignatureReader m_sigReader;
66 protected CodeReader m_codeReader;
67 protected ISymbolReader m_symbolReader;
69 internal AssemblyNameReference Corlib {
74 foreach (AssemblyNameReference ar in m_module.AssemblyReferences) {
75 if (ar.Name == Constants.Corlib) {
85 public ModuleDefinition Module {
86 get { return m_module; }
89 public SignatureReader SigReader {
90 get { return m_sigReader; }
93 public MetadataTableReader TableReader {
94 get { return m_tableReader; }
97 public CodeReader Code {
98 get { return m_codeReader; }
101 public ISymbolReader SymbolReader {
102 get { return m_symbolReader; }
103 set { m_symbolReader = value; }
106 public MetadataRoot MetadataRoot {
107 get { return m_root; }
110 public ReflectionReader (ModuleDefinition 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;
124 public TypeDefinition GetTypeDefAt (uint rid)
126 if (rid > m_typeDefs.Length)
129 return m_typeDefs [rid - 1];
132 public TypeReference GetTypeRefAt (uint rid)
134 if (rid > m_typeRefs.Length)
137 return m_typeRefs [rid - 1];
140 public TypeReference GetTypeSpecAt (uint rid, GenericContext context)
142 if (rid > m_typeSpecs.Length)
145 int index = (int) rid - 1;
147 TypeSpecTable tsTable = m_tableReader.GetTypeSpecTable ();
148 TypeSpecRow tsRow = tsTable [index];
149 TypeSpec ts = m_sigReader.GetTypeSpec (tsRow.Signature);
151 // don't cache context dependent generic stuff
152 if (IsGenericTypeSpec (ts.Type.ElementType))
153 return CreateTypeSpecFromSig (ts, index, context);
155 TypeReference tspec = m_typeSpecs [index];
159 tspec = CreateTypeSpecFromSig (ts, index, context);
160 m_typeSpecs [index] = tspec;
165 static bool IsGenericTypeSpec (ElementType etype)
167 return etype == ElementType.GenericInst
168 || etype == ElementType.Var
169 || etype == ElementType.MVar;
172 TypeReference CreateTypeSpecFromSig (TypeSpec ts, int index, GenericContext context)
174 TypeReference tspec = GetTypeRefFromSig (ts.Type, context);
175 tspec = GetModifierType (ts.CustomMods, tspec);
176 tspec.MetadataToken = MetadataToken.FromMetadataRow (TokenType.TypeSpec, index);
180 public FieldDefinition GetFieldDefAt (uint rid)
182 if (rid > m_fields.Length)
185 return m_fields [rid - 1];
188 public MethodDefinition GetMethodDefAt (uint rid)
190 if (rid > m_meths.Length)
193 return m_meths [rid - 1];
196 protected bool IsDeleted (IMemberDefinition member)
201 if (!member.IsSpecialName || !member.IsRuntimeSpecialName)
204 return member.Name.StartsWith (Constants.Deleted);
207 public MemberReference GetMemberRefAt (uint rid, GenericContext context)
209 if (rid > m_memberRefs.Length)
212 int index = (int) rid - 1;
213 MemberReference member = m_memberRefs [index];
217 MemberRefTable mrTable = m_tableReader.GetMemberRefTable ();
218 MemberRefRow mrefRow = mrTable [index];
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 ();
228 if (declaringType is GenericInstanceType) {
229 TypeReference ct = declaringType;
230 while (ct is GenericInstanceType)
231 ct = (ct as GenericInstanceType).ElementType;
236 if (sig is FieldSig) {
237 FieldSig fs = sig as FieldSig;
238 TypeReference fieldType = GetTypeRefFromSig (fs.Type, nc);
239 fieldType = GetModifierType (fs.CustomMods, fieldType);
241 member = new FieldReference (
242 m_root.Streams.StringsHeap [mrefRow.Name],
246 string name = m_root.Streams.StringsHeap [mrefRow.Name];
247 MethodSig ms = (MethodSig) sig;
249 member = CreateMethodReferenceFromSig (ms, name, declaringType, nc);
252 case TokenType.Method :
253 // really not sure about this
254 MethodDefinition methdef = GetMethodDefAt (mrefRow.Class.RID);
256 member = CreateMethodReferenceFromSig ((MethodSig) sig, methdef.Name, methdef.DeclaringType, new GenericContext ());
258 case TokenType.ModuleRef :
259 break; // TODO, implement that, or not
262 member.MetadataToken = MetadataToken.FromMetadataRow (TokenType.MemberRef, index);
263 m_module.MemberReferences.Add (member);
264 m_memberRefs [index] = member;
269 MethodReference CreateMethodReferenceFromSig (MethodSig ms, string name, TypeReference declaringType, GenericContext context)
271 MethodReference methref = new MethodReference (
272 name, ms.HasThis, ms.ExplicitThis, ms.MethCallConv);
273 methref.DeclaringType = declaringType;
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));
281 if (methref.GenericParameters.Count > 0)
282 context.Method = methref;
284 methref.ReturnType = GetMethodReturnType (ms, context);
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);
294 CreateSentinelIfNeeded (methref, ms);
299 public static void CreateSentinelIfNeeded (IMethodSignature meth, MethodSig signature)
301 MethodDefSig sig = signature as MethodDefSig;
305 int sentinel = sig.Sentinel;
307 if (sig.Sentinel < 0 || sig.Sentinel >= meth.Parameters.Count)
310 ParameterDefinition param = meth.Parameters [sentinel];
311 param.ParameterType = new SentinelType (param.ParameterType);
314 public PropertyDefinition GetPropertyDefAt (uint rid)
316 if (rid > m_properties.Length)
319 return m_properties [rid - 1];
322 public EventDefinition GetEventDefAt (uint rid)
324 if (rid > m_events.Length)
327 return m_events [rid - 1];
330 public ParameterDefinition GetParamDefAt (uint rid)
332 if (rid > m_parameters.Length)
335 return m_parameters [rid - 1];
338 public GenericParameter GetGenericParameterAt (uint rid)
340 if (rid > m_genericParameters.Length)
343 return m_genericParameters [rid - 1];
346 public GenericInstanceMethod GetMethodSpecAt (uint rid, GenericContext context)
348 if (rid > m_methodSpecs.Length)
351 int index = (int) rid - 1;
352 GenericInstanceMethod gim = m_methodSpecs [index];
356 MethodSpecTable msTable = m_tableReader.GetMethodSpecTable ();
357 MethodSpecRow msRow = msTable [index];
359 MethodSpec sig = m_sigReader.GetMethodSpec (msRow.Instantiation);
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);
367 throw new ReflectionException ("Unknown method type for method spec");
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));
374 m_methodSpecs [index] = gim;
379 public TypeReference GetTypeDefOrRef (MetadataToken token, GenericContext context)
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);
396 public TypeReference SearchCoreType (string fullName)
399 return m_module.Types [fullName];
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);
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;
432 public IMetadataTokenProvider LookupByToken (MetadataToken token)
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);
450 throw new NotSupportedException ("Lookup is not allowed on this kind of token");
454 public CustomAttribute GetCustomAttribute (MethodReference ctor, byte [] data, bool resolve)
456 CustomAttrib sig = m_sigReader.GetCustomAttrib (data, ctor, resolve);
457 return BuildCustomAttribute (ctor, data, sig);
460 public CustomAttribute GetCustomAttribute (MethodReference ctor, byte [] data)
462 return GetCustomAttribute (ctor, data, false);
465 public override void VisitModuleDefinition (ModuleDefinition mod)
467 VisitTypeDefinitionCollection (mod.Types);
470 public override void VisitTypeDefinitionCollection (TypeDefinitionCollection types)
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],
481 t.MetadataToken = MetadataToken.FromMetadataRow (TokenType.TypeDef, i);
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];
492 TypeDefinition parent = GetTypeDefAt (row.EnclosingClass);
493 TypeDefinition child = GetTypeDefAt (row.NestedClass);
495 if (!IsDeleted (child))
496 parent.NestedTypes.Add (child);
500 foreach (TypeDefinition type in m_typeDefs)
501 if (!IsDeleted (type))
505 if (m_tHeap.HasTable (TypeRefTable.RId)) {
506 TypeRefTable typesRef = m_tableReader.GetTypeRefTable ();
508 m_typeRefs = new TypeReference [typesRef.Rows.Count];
510 for (int i = 0; i < typesRef.Rows.Count; i++)
511 AddTypeRef (typesRef, i);
513 m_typeRefs = new TypeReference [0];
519 ReadGenericParameters ();
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));
530 ReadMemberReferences ();
533 void AddTypeRef (TypeRefTable typesRef, int i)
535 if (i >= typesRef.Rows.Count)
538 // Check if index has been already added.
539 if (m_typeRefs [i] != null)
542 TypeRefRow type = typesRef [i];
543 IMetadataScope scope = null;
544 TypeReference parent = null;
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];
552 case TokenType.ModuleRef:
553 scope = m_module.ModuleReferences [rid];
555 case TokenType.Module:
556 scope = m_module.Assembly.Modules [rid];
558 case TokenType.TypeRef:
559 AddTypeRef (typesRef, rid);
560 parent = GetTypeRefAt (type.ResolutionScope.RID);
562 scope = parent.Scope;
567 TypeReference t = new TypeReference (
568 m_root.Streams.StringsHeap [type.Name],
569 m_root.Streams.StringsHeap [type.Namespace],
571 t.MetadataToken = MetadataToken.FromMetadataRow (TokenType.TypeRef, i);
574 t.DeclaringType = parent;
577 m_module.TypeReferences.Add (t);
580 void ReadTypeSpecs ()
582 if (!m_tHeap.HasTable (TypeSpecTable.RId))
585 TypeSpecTable tsTable = m_tableReader.GetTypeSpecTable ();
586 m_typeSpecs = new TypeReference [tsTable.Rows.Count];
589 void ReadMethodSpecs ()
591 if (!m_tHeap.HasTable (MethodSpecTable.RId))
594 MethodSpecTable msTable = m_tableReader.GetMethodSpecTable ();
595 m_methodSpecs = new GenericInstanceMethod [msTable.Rows.Count];
598 void ReadGenericParameters ()
600 if (!m_tHeap.HasTable (GenericParamTable.RId))
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);
613 throw new ReflectionException ("Unknown owner type for generic parameter");
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);
620 owner.GenericParameters.Add (gp);
621 m_genericParameters [i] = gp;
625 void ReadAllFields ()
627 TypeDefTable tdefTable = m_tableReader.GetTypeDefTable ();
629 if (!m_tHeap.HasTable (FieldTable.RId)) {
630 m_fields = new FieldDefinition [0];
634 FieldTable fldTable = m_tableReader.GetFieldTable ();
635 m_fields = new FieldDefinition [fldTable.Rows.Count];
637 for (int i = 0; i < m_typeDefs.Length; i++) {
638 TypeDefinition dec = m_typeDefs [i];
639 GenericContext context = new GenericContext (dec);
643 if (index == tdefTable.Rows.Count - 1)
644 next = fldTable.Rows.Count + 1;
646 next = (int) (tdefTable [index + 1]).FieldList;
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);
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);
657 if (fsig.CustomMods.Length > 0)
658 fdef.FieldType = GetModifierType (fsig.CustomMods, fdef.FieldType);
660 if (!IsDeleted (fdef))
661 dec.Fields.Add (fdef);
663 m_fields [j - 1] = fdef;
670 if (!m_tHeap.HasTable (MethodTable.RId)) {
671 m_meths = new MethodDefinition [0];
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],
683 meth.ImplAttributes = mRow.ImplFlags;
685 meth.MetadataToken = MetadataToken.FromMetadataRow (TokenType.Method, i);
691 void CompleteMethods ()
693 TypeDefTable tdefTable = m_tableReader.GetTypeDefTable ();
695 if (!m_tHeap.HasTable (MethodTable.RId)) {
696 m_meths = new MethodDefinition [0];
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];
705 m_parameters = new ParameterDefinition [paramTable.Rows.Count];
707 for (int i = 0; i < m_typeDefs.Length; i++) {
708 TypeDefinition dec = m_typeDefs [i];
712 if (index == tdefTable.Rows.Count - 1)
713 next = methTable.Rows.Count + 1;
715 next = (int) (tdefTable [index + 1]).MethodList;
717 for (int j = (int) tdefTable [index].MethodList; j < next; j++) {
718 MethodRow methRow = methTable [j - 1];
719 MethodDefinition mdef = m_meths [j - 1];
721 if (!IsDeleted (mdef)) {
722 if (mdef.IsConstructor)
723 dec.Constructors.Add (mdef);
725 dec.Methods.Add (mdef);
728 GenericContext context = new GenericContext (mdef);
730 MethodDefSig msig = m_sigReader.GetMethodDefSig (methRow.Signature);
731 mdef.HasThis = msig.HasThis;
732 mdef.ExplicitThis = msig.ExplicitThis;
733 mdef.CallingConvention = msig.MethCallConv;
736 if (j == methTable.Rows.Count)
737 prms = m_parameters.Length + 1;
739 prms = (int) (methTable [j]).ParamList;
741 ParameterDefinition retparam = null;
743 //TODO: optimize this
744 int start = (int) methRow.ParamList - 1;
746 if (paramTable != null && start < prms - 1) {
748 ParamRow pRetRow = paramTable [start];
750 if (pRetRow != null && pRetRow.Sequence == 0) { // ret type
752 retparam = new ParameterDefinition (
753 m_root.Streams.StringsHeap [pRetRow.Name],
758 retparam.Method = mdef;
759 m_parameters [start] = retparam;
764 for (int k = 0; k < msig.ParamCount; k++) {
766 int pointer = start + k;
768 ParamRow pRow = null;
770 if (paramTable != null && pointer < prms - 1)
771 pRow = paramTable [pointer];
773 Param psig = msig.Parameters [k];
775 ParameterDefinition pdef;
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;
783 pdef = BuildParameterDefinition (k + 1, psig, context);
786 mdef.Parameters.Add (pdef);
789 mdef.ReturnType = GetMethodReturnType (msig, context);
790 MethodReturnType mrt = mdef.ReturnType;
792 if (retparam != null) {
793 mrt.Parameter = retparam;
794 mrt.Parameter.ParameterType = mrt.ReturnType;
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);
804 void ReadMemberReferences ()
806 if (!m_tHeap.HasTable (MemberRefTable.RId))
809 MemberRefTable mrefTable = m_tableReader.GetMemberRefTable ();
810 m_memberRefs = new MemberReference [mrefTable.Rows.Count];
813 public override void VisitExternTypeCollection (ExternTypeCollection externs)
815 ExternTypeCollection ext = externs;
817 if (!m_tHeap.HasTable (ExportedTypeTable.RId))
820 ExportedTypeTable etTable = m_tableReader.GetExportedTypeTable ();
821 TypeReference [] buffer = new TypeReference [etTable.Rows.Count];
823 for (int i = 0; i < etTable.Rows.Count; i++) {
824 ExportedTypeRow etRow = etTable [i];
826 buffer [i] = new TypeDefinition (
827 m_root.Streams.StringsHeap [etRow.TypeName],
828 m_root.Streams.StringsHeap [etRow.TypeNamespace],
830 buffer [i].AttachToScope (GetExportedTypeScope (etRow.Implementation));
833 for (int i = 0; i < etTable.Rows.Count; i++) {
834 ExportedTypeRow etRow = etTable [i];
835 if (etRow.Implementation.TokenType != TokenType.ExportedType)
838 TypeReference exported = buffer [i];
839 TypeReference owner = buffer [etRow.Implementation.RID - 1];
840 exported.DeclaringType = owner;
841 exported.AttachToScope (owner.Scope);
844 for (int i = 0; i < buffer.Length; i++) {
845 TypeReference curs = buffer [i];
851 IMetadataScope GetExportedTypeScope (MetadataToken scope)
853 int index = (int) scope.RID - 1;
854 switch (scope.TokenType) {
855 case TokenType.AssemblyRef:
856 return Module.AssemblyReferences [index];
858 return Module.ModuleReferences [index];
859 case TokenType.ExportedType:
860 return null; // resolved later
862 throw new NotSupportedException ();
866 static object GetFixedArgValue (CustomAttrib.FixedArg fa)
869 object [] vals = new object [fa.NumElem];
870 for (int j = 0; j < vals.Length; j++)
871 vals [j] = fa.Elems [j].Value;
874 return fa.Elems [0].Value;
877 TypeReference GetFixedArgType (CustomAttrib.FixedArg fa)
881 return new ArrayType (SearchCoreType (Constants.Object));
883 return new ArrayType (fa.Elems [0].ElemType);
885 return fa.Elems [0].ElemType;
888 TypeReference GetNamedArgType (CustomAttrib.NamedArg na)
890 if (na.FieldOrPropType == ElementType.Boxed)
891 return SearchCoreType (Constants.Object);
893 return GetFixedArgType (na.FixedArg);
896 protected CustomAttribute BuildCustomAttribute (MethodReference ctor, byte [] data, CustomAttrib sig)
898 CustomAttribute cattr = new CustomAttribute (ctor);
900 cattr.Resolved = false;
905 foreach (CustomAttrib.FixedArg fa in sig.FixedArgs)
906 cattr.ConstructorParameters.Add (GetFixedArgValue (fa));
908 foreach (CustomAttrib.NamedArg na in sig.NamedArgs) {
909 object value = GetFixedArgValue (na.FixedArg);
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));
917 throw new ReflectionException ("Non valid named arg");
923 void CompleteParameter (ParameterDefinition parameter, Param signature, GenericContext context)
925 TypeReference paramType;
927 if (signature.TypedByRef)
928 paramType = SearchCoreType (Constants.TypedReference);
930 paramType = GetTypeRefFromSig (signature.Type, context);
932 paramType = GetModifierType (signature.CustomMods, paramType);
935 paramType = new ReferenceType (paramType);
937 parameter.ParameterType = paramType;
940 public ParameterDefinition BuildParameterDefinition (int sequence, Param psig, GenericContext context)
942 ParameterDefinition parameter = new ParameterDefinition (null);
943 parameter.Sequence = sequence;
945 CompleteParameter (parameter, psig, context);
950 public ParameterDefinition BuildParameterDefinition (string name, int sequence, ParameterAttributes attrs, Param psig, GenericContext context)
952 ParameterDefinition parameter = new ParameterDefinition (name, sequence, attrs, null);
954 CompleteParameter (parameter, psig, context);
959 protected SecurityDeclaration BuildSecurityDeclaration (DeclSecurityRow dsRow)
961 return BuildSecurityDeclaration (dsRow.Action, m_root.Streams.BlobHeap.Read (dsRow.PermissionSet));
964 public SecurityDeclaration BuildSecurityDeclaration (SecurityAction action, byte [] permset)
966 if (m_secReader == null)
967 m_secReader = new SecurityDeclarationReader (m_root, this);
969 return m_secReader.FromByteArray (action, permset);
972 protected MarshalSpec BuildMarshalDesc (MarshalSig ms, IHasMarshalSpec container)
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;
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;
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;
996 } else if (ms.Spec is MarshalSig.FixedSysString) {
997 FixedSysStringSpec fssc = new FixedSysStringSpec (container);
998 fssc.Size = ((MarshalSig.FixedSysString) ms.Spec).Size;
1000 } else if (ms.Spec is MarshalSig.SafeArray) {
1001 SafeArraySpec sad = new SafeArraySpec (container);
1002 sad.ElemType = ((MarshalSig.SafeArray) ms.Spec).ArrayElemType;
1005 return new MarshalSpec (ms.NativeInstrinsic, container);
1009 public TypeReference GetModifierType (CustomMod [] cmods, TypeReference type)
1011 if (cmods == null || cmods.Length == 0)
1014 TypeReference ret = type;
1015 for (int i = cmods.Length - 1; i >= 0; i--) {
1016 CustomMod cmod = cmods [i];
1017 TypeReference modType;
1019 if (cmod.TypeDefOrRef.RID == 0)
1022 if (cmod.TypeDefOrRef.TokenType == TokenType.TypeDef)
1023 modType = GetTypeDefAt (cmod.TypeDefOrRef.RID);
1025 modType = GetTypeRefAt (cmod.TypeDefOrRef.RID);
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);
1035 public MethodReturnType GetMethodReturnType (MethodSig msig, GenericContext context)
1037 TypeReference retType;
1038 if (msig.RetType.Void)
1039 retType = SearchCoreType (Constants.Void);
1040 else if (msig.RetType.TypedByRef)
1041 retType = SearchCoreType (Constants.TypedReference);
1043 retType = GetTypeRefFromSig (msig.RetType.Type, context);
1045 retType = GetModifierType (msig.RetType.CustomMods, retType);
1047 if (msig.RetType.ByRef)
1048 retType = new ReferenceType (retType);
1050 return new MethodReturnType (retType);
1053 public TypeReference GetTypeRefFromSig (SigType t, GenericContext context)
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;
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));
1107 case ElementType.Ptr :
1108 PTR pointer = t as PTR;
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));
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));
1122 CreateSentinelIfNeeded (fnptr, funcptr.Method);
1125 case ElementType.Var:
1127 context.CheckProvider (context.Type, var.Index + 1);
1129 if (context.Type is GenericInstanceType)
1130 return (context.Type as GenericInstanceType).GenericArguments [var.Index];
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);
1137 if (context.Method is GenericInstanceMethod)
1138 return (context.Method as GenericInstanceMethod).GenericArguments [mvar.Index];
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);
1147 for (int i = 0; i < ginst.Signature.Arity; i++)
1148 instance.GenericArguments.Add (GetGenericArg (
1149 ginst.Signature.Types [i], context));
1158 TypeReference GetGenericArg (GenericArg arg, GenericContext context)
1160 TypeReference type = GetTypeRefFromSig (arg.Type, context);
1161 type = GetModifierType (arg.CustomMods, type);
1165 static bool IsOdd (int i)
1167 return (i & 1) == 1;
1170 protected object GetConstant (uint pos, ElementType elemType)
1172 if (elemType == ElementType.Class)
1175 byte [] constant = m_root.Streams.BlobHeap.Read (pos);
1177 if (elemType == ElementType.String) {
1178 int length = constant.Length;
1182 return Encoding.Unicode.GetString (constant, 0, length);
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
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
1197 if (BitConverter.IsLittleEndian)
1198 return GetConstantLittleEndian (elemType, constant);
1200 return GetConstantBigEndian (elemType, constant);
1204 static object GetConstantLittleEndian (ElementType elemType, byte [] constant)
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);
1226 throw new ReflectionException ("Non valid element in constant table");
1230 static object GetConstantBigEndian (ElementType elemType, byte [] constant)
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));
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 ();
1255 throw new ReflectionException ("Non valid element in constant table");
1259 protected void SetInitialValue (FieldDefinition field)
1262 TypeReference fieldType = field.FieldType;
1263 switch (fieldType.FullName) {
1264 case Constants.Boolean:
1265 case Constants.Byte:
1266 case Constants.SByte:
1269 case Constants.Int16:
1270 case Constants.UInt16:
1271 case Constants.Char:
1274 case Constants.Int32:
1275 case Constants.UInt32:
1276 case Constants.Single:
1279 case Constants.Int64:
1280 case Constants.UInt64:
1281 case Constants.Double:
1285 fieldType = fieldType.GetOriginalType ();
1287 TypeDefinition fieldTypeDef = fieldType as TypeDefinition;
1289 if (fieldTypeDef != null)
1290 size = (int) fieldTypeDef.ClassSize;
1294 if (size > 0 && field.RVA != RVA.Zero) {
1295 byte [] data = new byte [size];
1296 Section sect = m_reader.Image.GetSectionAtVirtualAddress (field.RVA);
1298 Buffer.BlockCopy (sect.Data, (int) (long) (field.RVA - sect.VirtualAddress), data, 0, size);
1299 field.InitialValue = data;
1301 field.InitialValue = new byte [0];