Merged pull request #58 from XTZGZoReX/master.
[mono.git] / mcs / class / IKVM.Reflection / Module.cs
1 /*
2   Copyright (C) 2009-2011 Jeroen Frijters
3
4   This software is provided 'as-is', without any express or implied
5   warranty.  In no event will the authors be held liable for any damages
6   arising from the use of this software.
7
8   Permission is granted to anyone to use this software for any purpose,
9   including commercial applications, and to alter it and redistribute it
10   freely, subject to the following restrictions:
11
12   1. The origin of this software must not be misrepresented; you must not
13      claim that you wrote the original software. If you use this software
14      in a product, an acknowledgment in the product documentation would be
15      appreciated but is not required.
16   2. Altered source versions must be plainly marked as such, and must not be
17      misrepresented as being the original software.
18   3. This notice may not be removed or altered from any source distribution.
19
20   Jeroen Frijters
21   jeroen@frijters.net
22   
23 */
24 using System;
25 using System.Collections.Generic;
26 using IKVM.Reflection.Metadata;
27 using IKVM.Reflection.Reader;
28
29 namespace IKVM.Reflection
30 {
31         public sealed class RawModule : IDisposable
32         {
33                 private readonly ModuleReader module;
34                 private readonly bool isManifestModule;
35                 private bool imported;
36
37                 internal RawModule(ModuleReader module)
38                 {
39                         this.module = module;
40                         this.isManifestModule = module.Assembly != null;
41                 }
42
43                 public string Location
44                 {
45                         get { return module.FullyQualifiedName; }
46                 }
47
48                 public bool IsManifestModule
49                 {
50                         get { return isManifestModule; }
51                 }
52
53                 private void CheckManifestModule()
54                 {
55                         if (!IsManifestModule)
56                         {
57                                 throw new BadImageFormatException("Module does not contain a manifest");
58                         }
59                 }
60
61                 public AssemblyName GetAssemblyName()
62                 {
63                         CheckManifestModule();
64                         return module.Assembly.GetName();
65                 }
66
67                 public AssemblyName[] GetReferencedAssemblies()
68                 {
69                         return module.__GetReferencedAssemblies();
70                 }
71
72                 public void Dispose()
73                 {
74                         if (!imported)
75                         {
76                                 module.stream.Dispose();
77                         }
78                 }
79
80                 internal Assembly ToAssembly()
81                 {
82                         if (imported)
83                         {
84                                 throw new InvalidOperationException();
85                         }
86                         imported = true;
87                         return module.Assembly;
88                 }
89
90                 internal Module ToModule(Assembly assembly)
91                 {
92                         if (module.Assembly != null)
93                         {
94                                 throw new InvalidOperationException();
95                         }
96                         imported = true;
97                         module.SetAssembly(assembly);
98                         return module;
99                 }
100         }
101
102         public abstract class Module : ICustomAttributeProvider
103         {
104                 internal readonly Universe universe;
105                 internal readonly ModuleTable ModuleTable = new ModuleTable();
106                 internal readonly TypeRefTable TypeRef = new TypeRefTable();
107                 internal readonly TypeDefTable TypeDef = new TypeDefTable();
108                 internal readonly FieldPtrTable FieldPtr = new FieldPtrTable();
109                 internal readonly FieldTable Field = new FieldTable();
110                 internal readonly MemberRefTable MemberRef = new MemberRefTable();
111                 internal readonly ConstantTable Constant = new ConstantTable();
112                 internal readonly CustomAttributeTable CustomAttribute = new CustomAttributeTable();
113                 internal readonly FieldMarshalTable FieldMarshal = new FieldMarshalTable();
114                 internal readonly DeclSecurityTable DeclSecurity = new DeclSecurityTable();
115                 internal readonly ClassLayoutTable ClassLayout = new ClassLayoutTable();
116                 internal readonly FieldLayoutTable FieldLayout = new FieldLayoutTable();
117                 internal readonly ParamPtrTable ParamPtr = new ParamPtrTable();
118                 internal readonly ParamTable Param = new ParamTable();
119                 internal readonly InterfaceImplTable InterfaceImpl = new InterfaceImplTable();
120                 internal readonly StandAloneSigTable StandAloneSig = new StandAloneSigTable();
121                 internal readonly EventMapTable EventMap = new EventMapTable();
122                 internal readonly EventPtrTable EventPtr = new EventPtrTable();
123                 internal readonly EventTable Event = new EventTable();
124                 internal readonly PropertyMapTable PropertyMap = new PropertyMapTable();
125                 internal readonly PropertyPtrTable PropertyPtr = new PropertyPtrTable();
126                 internal readonly PropertyTable Property = new PropertyTable();
127                 internal readonly MethodSemanticsTable MethodSemantics = new MethodSemanticsTable();
128                 internal readonly MethodImplTable MethodImpl = new MethodImplTable();
129                 internal readonly ModuleRefTable ModuleRef = new ModuleRefTable();
130                 internal readonly TypeSpecTable TypeSpec = new TypeSpecTable();
131                 internal readonly ImplMapTable ImplMap = new ImplMapTable();
132                 internal readonly FieldRVATable FieldRVA = new FieldRVATable();
133                 internal readonly AssemblyTable AssemblyTable = new AssemblyTable();
134                 internal readonly AssemblyRefTable AssemblyRef = new AssemblyRefTable();
135                 internal readonly MethodPtrTable MethodPtr = new MethodPtrTable();
136                 internal readonly MethodDefTable MethodDef = new MethodDefTable();
137                 internal readonly NestedClassTable NestedClass = new NestedClassTable();
138                 internal readonly FileTable File = new FileTable();
139                 internal readonly ExportedTypeTable ExportedType = new ExportedTypeTable();
140                 internal readonly ManifestResourceTable ManifestResource = new ManifestResourceTable();
141                 internal readonly GenericParamTable GenericParam = new GenericParamTable();
142                 internal readonly MethodSpecTable MethodSpec = new MethodSpecTable();
143                 internal readonly GenericParamConstraintTable GenericParamConstraint = new GenericParamConstraintTable();
144
145                 protected Module(Universe universe)
146                 {
147                         this.universe = universe;
148                 }
149
150                 internal Table[] GetTables()
151                 {
152                         Table[] tables = new Table[64];
153                         tables[ModuleTable.Index] = ModuleTable;
154                         tables[TypeRefTable.Index] = TypeRef;
155                         tables[TypeDefTable.Index] = TypeDef;
156                         tables[FieldPtrTable.Index] = FieldPtr;
157                         tables[FieldTable.Index] = Field;
158                         tables[MemberRefTable.Index] = MemberRef;
159                         tables[ConstantTable.Index] = Constant;
160                         tables[CustomAttributeTable.Index] = CustomAttribute;
161                         tables[FieldMarshalTable.Index] = FieldMarshal;
162                         tables[DeclSecurityTable.Index] = DeclSecurity;
163                         tables[ClassLayoutTable.Index] = ClassLayout;
164                         tables[FieldLayoutTable.Index] = FieldLayout;
165                         tables[ParamPtrTable.Index] = ParamPtr;
166                         tables[ParamTable.Index] = Param;
167                         tables[InterfaceImplTable.Index] = InterfaceImpl;
168                         tables[StandAloneSigTable.Index] = StandAloneSig;
169                         tables[EventMapTable.Index] = EventMap;
170                         tables[EventPtrTable.Index] = EventPtr;
171                         tables[EventTable.Index] = Event;
172                         tables[PropertyMapTable.Index] = PropertyMap;
173                         tables[PropertyPtrTable.Index] = PropertyPtr;
174                         tables[PropertyTable.Index] = Property;
175                         tables[MethodSemanticsTable.Index] = MethodSemantics;
176                         tables[MethodImplTable.Index] = MethodImpl;
177                         tables[ModuleRefTable.Index] = ModuleRef;
178                         tables[TypeSpecTable.Index] = TypeSpec;
179                         tables[ImplMapTable.Index] = ImplMap;
180                         tables[FieldRVATable.Index] = FieldRVA;
181                         tables[AssemblyTable.Index] = AssemblyTable;
182                         tables[AssemblyRefTable.Index] = AssemblyRef;
183                         tables[MethodPtrTable.Index] = MethodPtr;
184                         tables[MethodDefTable.Index] = MethodDef;
185                         tables[NestedClassTable.Index] = NestedClass;
186                         tables[FileTable.Index] = File;
187                         tables[ExportedTypeTable.Index] = ExportedType;
188                         tables[ManifestResourceTable.Index] = ManifestResource;
189                         tables[GenericParamTable.Index] = GenericParam;
190                         tables[MethodSpecTable.Index] = MethodSpec;
191                         tables[GenericParamConstraintTable.Index] = GenericParamConstraint;
192                         return tables;
193                 }
194
195                 public virtual void __GetDataDirectoryEntry(int index, out int rva, out int length)
196                 {
197                         throw new NotSupportedException();
198                 }
199
200                 public virtual long __RelativeVirtualAddressToFileOffset(int rva)
201                 {
202                         throw new NotSupportedException();
203                 }
204
205                 public virtual bool __GetSectionInfo(int rva, out string name, out int characteristics)
206                 {
207                         throw new NotSupportedException();
208                 }
209
210                 public virtual int __ReadDataFromRVA(int rva, byte[] data, int offset, int length)
211                 {
212                         throw new NotSupportedException();
213                 }
214
215                 public virtual void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine)
216                 {
217                         throw new NotSupportedException();
218                 }
219
220                 public virtual int __Subsystem
221                 {
222                         get { throw new NotSupportedException(); }
223                 }
224
225                 public FieldInfo GetField(string name)
226                 {
227                         return GetField(name, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
228                 }
229
230                 public FieldInfo GetField(string name, BindingFlags bindingFlags)
231                 {
232                         return IsResource() ? null : GetModuleType().GetField(name, bindingFlags | BindingFlags.DeclaredOnly);
233                 }
234
235                 public FieldInfo[] GetFields()
236                 {
237                         return GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
238                 }
239
240                 public FieldInfo[] GetFields(BindingFlags bindingFlags)
241                 {
242                         return IsResource() ? Empty<FieldInfo>.Array : GetModuleType().GetFields(bindingFlags | BindingFlags.DeclaredOnly);
243                 }
244
245                 public MethodInfo GetMethod(string name)
246                 {
247                         return IsResource() ? null : GetModuleType().GetMethod(name, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
248                 }
249
250                 public MethodInfo GetMethod(string name, Type[] types)
251                 {
252                         return IsResource() ? null : GetModuleType().GetMethod(name, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly, null, types, null);
253                 }
254
255                 public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConv, Type[] types, ParameterModifier[] modifiers)
256                 {
257                         return IsResource() ? null : GetModuleType().GetMethod(name, bindingAttr | BindingFlags.DeclaredOnly, binder, callConv, types, modifiers);
258                 }
259
260                 public MethodInfo[] GetMethods()
261                 {
262                         return GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
263                 }
264
265                 public MethodInfo[] GetMethods(BindingFlags bindingFlags)
266                 {
267                         return IsResource() ? Empty<MethodInfo>.Array : GetModuleType().GetMethods(bindingFlags | BindingFlags.DeclaredOnly);
268                 }
269
270                 public ConstructorInfo __ModuleInitializer
271                 {
272                         get { return IsResource() ? null : GetModuleType().TypeInitializer; }
273                 }
274
275                 public byte[] ResolveSignature(int metadataToken)
276                 {
277                         ModuleReader rdr = this as ModuleReader;
278                         if (rdr != null)
279                         {
280                                 ByteReader br = rdr.ResolveSignature(metadataToken);
281                                 return br.ReadBytes(br.Length);
282                         }
283                         throw new NotSupportedException();
284                 }
285
286                 public virtual __StandAloneMethodSig __ResolveStandAloneMethodSig(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
287                 {
288                         throw new NotSupportedException();
289                 }
290
291                 public int MetadataToken
292                 {
293                         get { return IsResource() ? 0 : 1; }
294                 }
295
296                 public abstract int MDStreamVersion { get ;}
297                 public abstract Assembly Assembly { get; }
298                 public abstract string FullyQualifiedName { get; }
299                 public abstract string Name { get; }
300                 public abstract Guid ModuleVersionId { get; }
301                 public abstract Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments);
302                 public abstract MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments);
303                 public abstract FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments);
304                 public abstract MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments);
305
306                 public abstract string ResolveString(int metadataToken);
307                 public abstract Type[] __ResolveOptionalParameterTypes(int metadataToken);
308                 public abstract string ScopeName { get; }
309
310                 internal abstract void GetTypesImpl(List<Type> list);
311
312                 internal abstract Type FindType(TypeName name);
313
314                 public Type GetType(string className)
315                 {
316                         return GetType(className, false, false);
317                 }
318
319                 public Type GetType(string className, bool ignoreCase)
320                 {
321                         return GetType(className, false, ignoreCase);
322                 }
323
324                 public Type GetType(string className, bool throwOnError, bool ignoreCase)
325                 {
326                         if (ignoreCase)
327                         {
328                                 throw new NotImplementedException();
329                         }
330                         TypeNameParser parser = TypeNameParser.Parse(className, throwOnError);
331                         if (parser.Error)
332                         {
333                                 return null;
334                         }
335                         if (parser.AssemblyName != null)
336                         {
337                                 if (throwOnError)
338                                 {
339                                         throw new ArgumentException("Type names passed to Module.GetType() must not specify an assembly.");
340                                 }
341                                 else
342                                 {
343                                         return null;
344                                 }
345                         }
346                         Type type = FindType(TypeName.Split(TypeNameParser.Unescape(parser.FirstNamePart)));
347                         if (type == null && __IsMissing)
348                         {
349                                 throw new MissingModuleException((MissingModule)this);
350                         }
351                         return parser.Expand(type, this.Assembly, throwOnError, className, false);
352                 }
353
354                 public Type[] GetTypes()
355                 {
356                         List<Type> list = new List<Type>();
357                         GetTypesImpl(list);
358                         return list.ToArray();
359                 }
360
361                 public Type[] FindTypes(TypeFilter filter, object filterCriteria)
362                 {
363                         List<Type> list = new List<Type>();
364                         foreach (Type type in GetTypes())
365                         {
366                                 if (filter(type, filterCriteria))
367                                 {
368                                         list.Add(type);
369                                 }
370                         }
371                         return list.ToArray();
372                 }
373
374                 public virtual bool IsResource()
375                 {
376                         return false;
377                 }
378
379                 public Type ResolveType(int metadataToken)
380                 {
381                         return ResolveType(metadataToken, null, null);
382                 }
383
384                 public MethodBase ResolveMethod(int metadataToken)
385                 {
386                         return ResolveMethod(metadataToken, null, null);
387                 }
388
389                 public FieldInfo ResolveField(int metadataToken)
390                 {
391                         return ResolveField(metadataToken, null, null);
392                 }
393
394                 public MemberInfo ResolveMember(int metadataToken)
395                 {
396                         return ResolveMember(metadataToken, null, null);
397                 }
398
399                 public bool IsDefined(Type attributeType, bool inherit)
400                 {
401                         return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit).Count != 0;
402                 }
403
404                 public IList<CustomAttributeData> __GetCustomAttributes(Type attributeType, bool inherit)
405                 {
406                         return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit);
407                 }
408
409                 public virtual IList<CustomAttributeData> __GetPlaceholderAssemblyCustomAttributes(bool multiple, bool security)
410                 {
411                         return Empty<CustomAttributeData>.Array;
412                 }
413
414                 public abstract AssemblyName[] __GetReferencedAssemblies();
415
416                 public virtual void __ResolveReferencedAssemblies(Assembly[] assemblies)
417                 {
418                         throw new NotSupportedException();
419                 }
420
421                 public abstract string[] __GetReferencedModules();
422
423                 public abstract Type[] __GetReferencedTypes();
424
425                 public abstract Type[] __GetExportedTypes();
426
427                 public virtual bool __IsMissing
428                 {
429                         get { return false; }
430                 }
431
432                 public long __ImageBase
433                 {
434                         get { return GetImageBaseImpl(); }
435                 }
436
437                 protected abstract long GetImageBaseImpl();
438
439                 public virtual long __StackReserve
440                 {
441                         get { throw new NotSupportedException(); }
442                 }
443
444                 public virtual byte[] __ModuleHash
445                 {
446                         get { throw new NotSupportedException(); }
447                 }
448
449                 public List<CustomAttributeData> __GetCustomAttributesFor(int token)
450                 {
451                         return GetCustomAttributes(token, null);
452                 }
453
454                 internal Type CanonicalizeType(Type type)
455                 {
456                         Type canon;
457                         if (!universe.canonicalizedTypes.TryGetValue(type, out canon))
458                         {
459                                 canon = type;
460                                 universe.canonicalizedTypes.Add(canon, canon);
461                         }
462                         return canon;
463                 }
464
465                 internal abstract Type GetModuleType();
466
467                 internal abstract ByteReader GetBlob(int blobIndex);
468
469                 internal virtual IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
470                 {
471                         return GetCustomAttributes(0x00000001, attributeType);
472                 }
473
474                 internal List<CustomAttributeData> GetCustomAttributes(int metadataToken, Type attributeType)
475                 {
476                         List<CustomAttributeData> list = new List<CustomAttributeData>();
477                         // TODO use binary search?
478                         for (int i = 0; i < CustomAttribute.records.Length; i++)
479                         {
480                                 if (CustomAttribute.records[i].Parent == metadataToken)
481                                 {
482                                         if (attributeType == null)
483                                         {
484                                                 list.Add(new CustomAttributeData(this, i));
485                                         }
486                                         else
487                                         {
488                                                 ConstructorInfo constructor = (ConstructorInfo)ResolveMethod(CustomAttribute.records[i].Type);
489                                                 if (attributeType.IsAssignableFrom(constructor.DeclaringType))
490                                                 {
491                                                         list.Add(new CustomAttributeData(this.Assembly, constructor, GetBlob(CustomAttribute.records[i].Value)));
492                                                 }
493                                         }
494                                 }
495                         }
496                         return list;
497                 }
498
499                 internal IList<CustomAttributeData> GetDeclarativeSecurity(int metadataToken)
500                 {
501                         List<CustomAttributeData> list = new List<CustomAttributeData>();
502                         // TODO use binary search?
503                         for (int i = 0; i < DeclSecurity.records.Length; i++)
504                         {
505                                 if (DeclSecurity.records[i].Parent == metadataToken)
506                                 {
507                                         int action = DeclSecurity.records[i].Action;
508                                         int permissionSet = DeclSecurity.records[i].PermissionSet;
509                                         CustomAttributeData.ReadDeclarativeSecurity(this.Assembly, list, action, GetBlob(permissionSet));
510                                 }
511                         }
512                         return list;
513                 }
514
515                 internal virtual void Dispose()
516                 {
517                 }
518
519                 internal virtual void ExportTypes(int fileToken, IKVM.Reflection.Emit.ModuleBuilder manifestModule)
520                 {
521                 }
522         }
523
524         abstract class NonPEModule : Module
525         {
526                 protected NonPEModule(Universe universe)
527                         : base(universe)
528                 {
529                 }
530
531                 protected virtual Exception InvalidOperationException()
532                 {
533                         return new InvalidOperationException();
534                 }
535
536                 protected virtual Exception NotSupportedException()
537                 {
538                         return new NotSupportedException();
539                 }
540
541                 protected virtual Exception ArgumentOutOfRangeException()
542                 {
543                         return new ArgumentOutOfRangeException();
544                 }
545
546                 internal sealed override Type GetModuleType()
547                 {
548                         throw InvalidOperationException();
549                 }
550
551                 internal sealed override ByteReader GetBlob(int blobIndex)
552                 {
553                         throw InvalidOperationException();
554                 }
555
556                 public sealed override AssemblyName[] __GetReferencedAssemblies()
557                 {
558                         throw NotSupportedException();
559                 }
560
561                 public sealed override string[] __GetReferencedModules()
562                 {
563                         throw NotSupportedException();
564                 }
565
566                 public override Type[] __GetReferencedTypes()
567                 {
568                         throw NotSupportedException();
569                 }
570
571                 public override Type[] __GetExportedTypes()
572                 {
573                         throw NotSupportedException();
574                 }
575
576                 protected sealed override long GetImageBaseImpl()
577                 {
578                         throw NotSupportedException();
579                 }
580
581                 public sealed override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
582                 {
583                         throw ArgumentOutOfRangeException();
584                 }
585
586                 public sealed override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
587                 {
588                         throw ArgumentOutOfRangeException();
589                 }
590
591                 public sealed override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
592                 {
593                         throw ArgumentOutOfRangeException();
594                 }
595
596                 public sealed override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
597                 {
598                         throw ArgumentOutOfRangeException();
599                 }
600
601                 public sealed override string ResolveString(int metadataToken)
602                 {
603                         throw ArgumentOutOfRangeException();
604                 }
605
606                 public sealed override Type[] __ResolveOptionalParameterTypes(int metadataToken)
607                 {
608                         throw ArgumentOutOfRangeException();
609                 }
610         }
611
612         public delegate bool TypeFilter(Type m, object filterCriteria);
613         public delegate bool MemberFilter(MemberInfo m, object filterCriteria);
614 }