2 Copyright (C) 2008-2012 Jeroen Frijters
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.
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:
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.
25 using System.Collections.Generic;
27 using System.Diagnostics;
28 using System.Diagnostics.SymbolStore;
29 using System.Security.Cryptography;
30 using System.Runtime.CompilerServices;
31 using System.Runtime.InteropServices;
32 using IKVM.Reflection.Impl;
33 using IKVM.Reflection.Metadata;
34 using IKVM.Reflection.Writer;
36 namespace IKVM.Reflection.Emit
38 public sealed class ModuleBuilder : Module, ITypeOwner
40 private static readonly bool usePublicKeyAssemblyReference = false;
41 private Guid mvid = Guid.NewGuid();
42 private long imageBaseAddress = 0x00400000;
43 private long stackReserve = -1;
44 private int fileAlignment = 0x200;
45 private DllCharacteristics dllCharacteristics = DllCharacteristics.DynamicBase | DllCharacteristics.NoSEH | DllCharacteristics.NXCompat | DllCharacteristics.TerminalServerAware;
46 private readonly AssemblyBuilder asm;
47 internal readonly string moduleName;
48 internal readonly string fileName;
49 internal readonly ISymbolWriterImpl symbolWriter;
50 private readonly TypeBuilder moduleType;
51 private readonly List<TypeBuilder> types = new List<TypeBuilder>();
52 private readonly Dictionary<Type, int> typeTokens = new Dictionary<Type, int>();
53 private readonly Dictionary<Type, int> memberRefTypeTokens = new Dictionary<Type, int>();
54 internal readonly ByteBuffer methodBodies = new ByteBuffer(128 * 1024);
55 internal readonly List<int> tokenFixupOffsets = new List<int>();
56 internal readonly ByteBuffer initializedData = new ByteBuffer(512);
57 internal readonly ByteBuffer manifestResources = new ByteBuffer(512);
58 internal ResourceSection unmanagedResources;
59 private readonly Dictionary<MemberInfo, int> importedMembers = new Dictionary<MemberInfo, int>();
60 private readonly Dictionary<MemberRefKey, int> importedMemberRefs = new Dictionary<MemberRefKey, int>();
61 private readonly Dictionary<Assembly, int> referencedAssemblies = new Dictionary<Assembly, int>();
62 private List<AssemblyName> referencedAssemblyNames;
63 private int nextPseudoToken = -1;
64 private readonly List<int> resolvedTokens = new List<int>();
65 internal readonly TableHeap Tables = new TableHeap();
66 internal readonly StringHeap Strings = new StringHeap();
67 internal readonly UserStringHeap UserStrings = new UserStringHeap();
68 internal readonly GuidHeap Guids = new GuidHeap();
69 internal readonly BlobHeap Blobs = new BlobHeap();
70 internal readonly List<VTableFixups> vtablefixups = new List<VTableFixups>();
71 internal readonly List<UnmanagedExport> unmanagedExports = new List<UnmanagedExport>();
72 private List<InterfaceImplCustomAttribute> interfaceImplCustomAttributes;
74 internal struct VTableFixups
76 internal uint initializedDataOffset;
77 internal ushort count;
80 internal int SlotWidth
82 get { return (type & 0x02) == 0 ? 4 : 8; }
86 struct InterfaceImplCustomAttribute
89 internal int interfaceType;
90 internal int pseudoToken;
93 struct MemberRefKey : IEquatable<MemberRefKey>
95 private readonly Type type;
96 private readonly string name;
97 private readonly Signature signature;
99 internal MemberRefKey(Type type, string name, Signature signature)
103 this.signature = signature;
106 public bool Equals(MemberRefKey other)
108 return other.type.Equals(type)
109 && other.name == name
110 && other.signature.Equals(signature);
113 public override bool Equals(object obj)
115 MemberRefKey? other = obj as MemberRefKey?;
116 return other != null && Equals(other);
119 public override int GetHashCode()
121 return type.GetHashCode() + name.GetHashCode() + signature.GetHashCode();
125 internal ModuleBuilder(AssemblyBuilder asm, string moduleName, string fileName, bool emitSymbolInfo)
129 this.moduleName = moduleName;
130 this.fileName = fileName;
133 symbolWriter = SymbolSupport.CreateSymbolWriterFor(this);
135 // <Module> must be the first record in the TypeDef table
136 moduleType = new TypeBuilder(this, null, "<Module>");
137 types.Add(moduleType);
140 internal void PopulatePropertyAndEventTables()
142 // LAMESPEC the PropertyMap and EventMap tables are not required to be sorted by the CLI spec,
143 // but .NET sorts them and Mono requires them to be sorted, so we have to populate the
144 // tables in the right order
145 foreach (TypeBuilder type in types)
147 type.PopulatePropertyAndEventTables();
151 internal void WriteTypeDefTable(MetadataWriter mw)
155 foreach (TypeBuilder type in types)
157 type.WriteTypeDefRecord(mw, ref fieldList, ref methodList);
161 internal void WriteMethodDefTable(int baseRVA, MetadataWriter mw)
164 foreach (TypeBuilder type in types)
166 type.WriteMethodDefRecords(baseRVA, mw, ref paramList);
170 internal void WriteParamTable(MetadataWriter mw)
172 foreach (TypeBuilder type in types)
174 type.WriteParamRecords(mw);
178 internal void WriteFieldTable(MetadataWriter mw)
180 foreach (TypeBuilder type in types)
182 type.WriteFieldRecords(mw);
186 internal int AllocPseudoToken()
188 return nextPseudoToken--;
191 public TypeBuilder DefineType(string name)
193 return DefineType(name, TypeAttributes.Class);
196 public TypeBuilder DefineType(string name, TypeAttributes attr)
198 return DefineType(name, attr, null);
201 public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent)
203 return DefineType(name, attr, parent, PackingSize.Unspecified, 0);
206 public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, int typesize)
208 return DefineType(name, attr, parent, PackingSize.Unspecified, typesize);
211 public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packsize)
213 return DefineType(name, attr, parent, packsize, 0);
216 public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, Type[] interfaces)
218 TypeBuilder tb = DefineType(name, attr, parent);
219 foreach (Type iface in interfaces)
221 tb.AddInterfaceImplementation(iface);
226 public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize)
229 int lastdot = name.LastIndexOf('.');
232 ns = name.Substring(0, lastdot);
233 name = name.Substring(lastdot + 1);
235 TypeBuilder typeBuilder = __DefineType(ns, name);
236 typeBuilder.__SetAttributes(attr);
237 typeBuilder.SetParent(parent);
238 if (packingSize != PackingSize.Unspecified || typesize != 0)
240 typeBuilder.__SetLayout((int)packingSize, typesize);
245 public TypeBuilder __DefineType(string ns, string name)
247 return DefineType(this, ns, name);
250 internal TypeBuilder DefineType(ITypeOwner owner, string ns, string name)
252 TypeBuilder typeBuilder = new TypeBuilder(owner, ns, name);
253 types.Add(typeBuilder);
257 public EnumBuilder DefineEnum(string name, TypeAttributes visibility, Type underlyingType)
259 TypeBuilder tb = DefineType(name, (visibility & TypeAttributes.VisibilityMask) | TypeAttributes.Sealed, universe.System_Enum);
260 FieldBuilder fb = tb.DefineField("value__", underlyingType, FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
261 return new EnumBuilder(tb, fb);
264 public FieldBuilder __DefineField(string name, Type type, CustomModifiers customModifiers, FieldAttributes attributes)
266 return moduleType.__DefineField(name, type, customModifiers, attributes);
269 [Obsolete("Please use __DefineField(string, Type, CustomModifiers, FieldAttributes) instead.")]
270 public FieldBuilder __DefineField(string name, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes)
272 return moduleType.DefineField(name, type, requiredCustomModifiers, optionalCustomModifiers, attributes);
275 public ConstructorBuilder __DefineModuleInitializer(MethodAttributes visibility)
277 return moduleType.DefineConstructor(visibility | MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, Type.EmptyTypes);
280 public FieldBuilder DefineUninitializedData(string name, int size, FieldAttributes attributes)
282 return moduleType.DefineUninitializedData(name, size, attributes);
285 public FieldBuilder DefineInitializedData(string name, byte[] data, FieldAttributes attributes)
287 return moduleType.DefineInitializedData(name, data, attributes);
290 public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)
292 return moduleType.DefineMethod(name, attributes, returnType, parameterTypes);
295 public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
297 return moduleType.DefineMethod(name, attributes, callingConvention, returnType, parameterTypes);
300 public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
302 return moduleType.DefineMethod(name, attributes, callingConvention, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
305 public MethodBuilder DefinePInvokeMethod(string name, string dllName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
307 return moduleType.DefinePInvokeMethod(name, dllName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
310 public MethodBuilder DefinePInvokeMethod(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
312 return moduleType.DefinePInvokeMethod(name, dllName, entryName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
315 public void CreateGlobalFunctions()
317 moduleType.CreateType();
320 internal void AddTypeForwarder(Type type)
323 if (!type.__IsMissing)
325 foreach (Type nested in type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic))
327 // we export all nested types (i.e. even the private ones)
328 // (this behavior is the same as the C# compiler)
329 AddTypeForwarder(nested);
334 private int ExportType(Type type)
336 ExportedTypeTable.Record rec = new ExportedTypeTable.Record();
337 rec.TypeDefId = type.MetadataToken;
338 rec.TypeName = this.Strings.Add(type.__Name);
339 string ns = type.__Namespace;
340 rec.TypeNamespace = ns == null ? 0 : this.Strings.Add(ns);
344 rec.Implementation = ExportType(type.DeclaringType);
348 rec.Flags = 0x00200000; // CorTypeAttr.tdForwarder
349 rec.Implementation = ImportAssemblyRef(type.Assembly);
351 return 0x27000000 | this.ExportedType.FindOrAddRecord(rec);
354 public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
356 SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
359 public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
361 SetCustomAttribute(0x00000001, customBuilder);
364 internal void SetCustomAttribute(int token, CustomAttributeBuilder customBuilder)
366 Debug.Assert(!customBuilder.IsPseudoCustomAttribute);
367 CustomAttributeTable.Record rec = new CustomAttributeTable.Record();
369 rec.Type = this.GetConstructorToken(customBuilder.Constructor).Token;
370 rec.Value = customBuilder.WriteBlob(this);
371 this.CustomAttribute.AddRecord(rec);
374 internal void AddDeclarativeSecurity(int token, System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet)
376 DeclSecurityTable.Record rec = new DeclSecurityTable.Record();
377 rec.Action = (short)securityAction;
379 // like Ref.Emit, we're using the .NET 1.x xml format
380 rec.PermissionSet = this.Blobs.Add(ByteBuffer.Wrap(System.Text.Encoding.Unicode.GetBytes(permissionSet.ToXml().ToString())));
381 this.DeclSecurity.AddRecord(rec);
384 internal void AddDeclarativeSecurity(int token, List<CustomAttributeBuilder> declarativeSecurity)
386 Dictionary<int, List<CustomAttributeBuilder>> ordered = new Dictionary<int, List<CustomAttributeBuilder>>();
387 foreach (CustomAttributeBuilder cab in declarativeSecurity)
390 // check for HostProtectionAttribute without SecurityAction
391 if (cab.ConstructorArgumentCount == 0)
393 action = (int)System.Security.Permissions.SecurityAction.LinkDemand;
397 action = (int)cab.GetConstructorArgument(0);
399 List<CustomAttributeBuilder> list;
400 if (!ordered.TryGetValue(action, out list))
402 list = new List<CustomAttributeBuilder>();
403 ordered.Add(action, list);
407 foreach (KeyValuePair<int, List<CustomAttributeBuilder>> kv in ordered)
409 DeclSecurityTable.Record rec = new DeclSecurityTable.Record();
410 rec.Action = (short)kv.Key;
412 rec.PermissionSet = WriteDeclSecurityBlob(kv.Value);
413 this.DeclSecurity.AddRecord(rec);
417 private int WriteDeclSecurityBlob(List<CustomAttributeBuilder> list)
420 if (list.Count == 1 && (xml = list[0].GetLegacyDeclSecurity()) != null)
422 // write .NET 1.1 format
423 return this.Blobs.Add(ByteBuffer.Wrap(System.Text.Encoding.Unicode.GetBytes(xml)));
425 ByteBuffer namedArgs = new ByteBuffer(100);
426 ByteBuffer bb = new ByteBuffer(list.Count * 100);
428 bb.WriteCompressedInt(list.Count);
429 foreach (CustomAttributeBuilder cab in list)
431 bb.Write(cab.Constructor.DeclaringType.AssemblyQualifiedName);
433 cab.WriteNamedArgumentsForDeclSecurity(this, namedArgs);
434 bb.WriteCompressedInt(namedArgs.Length);
437 return this.Blobs.Add(bb);
440 public void DefineManifestResource(string name, Stream stream, ResourceAttributes attribute)
442 manifestResources.Align(8);
443 ManifestResourceTable.Record rec = new ManifestResourceTable.Record();
444 rec.Offset = manifestResources.Position;
445 rec.Flags = (int)attribute;
446 rec.Name = this.Strings.Add(name);
447 rec.Implementation = 0;
448 this.ManifestResource.AddRecord(rec);
449 manifestResources.Write(0); // placeholder for the length
450 manifestResources.Write(stream);
451 int savePosition = manifestResources.Position;
452 manifestResources.Position = rec.Offset;
453 manifestResources.Write(savePosition - (manifestResources.Position + 4));
454 manifestResources.Position = savePosition;
457 public override Assembly Assembly
462 internal override Type FindType(TypeName name)
464 foreach (Type type in types)
466 if (type.__Namespace == name.Namespace && type.__Name == name.Name)
474 internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
476 foreach (Type type in types)
478 if (new TypeName(type.__Namespace, type.__Name).ToLowerInvariant() == lowerCaseName)
486 internal override void GetTypesImpl(List<Type> list)
488 foreach (Type type in types)
490 if (type != moduleType)
497 public ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType)
499 return symbolWriter.DefineDocument(url, language, languageVendor, documentType);
502 public int __GetAssemblyToken(Assembly assembly)
504 return ImportAssemblyRef(assembly);
507 public TypeToken GetTypeToken(string name)
509 return new TypeToken(GetType(name, true, false).MetadataToken);
512 public TypeToken GetTypeToken(Type type)
514 if (type.Module == this)
516 return new TypeToken(type.GetModuleBuilderToken());
520 return new TypeToken(ImportType(type));
524 internal int GetTypeTokenForMemberRef(Type type)
526 if (type.__IsMissing)
528 return ImportType(type);
530 else if (type.IsGenericTypeDefinition)
533 if (!memberRefTypeTokens.TryGetValue(type, out token))
535 ByteBuffer spec = new ByteBuffer(5);
536 Signature.WriteTypeSpec(this, spec, type);
537 token = 0x1B000000 | this.TypeSpec.AddRecord(this.Blobs.Add(spec));
538 memberRefTypeTokens.Add(type, token);
542 else if (type.IsModulePseudoType)
544 return 0x1A000000 | this.ModuleRef.FindOrAddRecord(this.Strings.Add(type.Module.ScopeName));
548 return GetTypeToken(type).Token;
552 private static bool IsFromGenericTypeDefinition(MemberInfo member)
554 Type decl = member.DeclaringType;
555 return decl != null && !decl.__IsMissing && decl.IsGenericTypeDefinition;
558 public FieldToken GetFieldToken(FieldInfo field)
560 // NOTE for some reason, when TypeBuilder.GetFieldToken() is used on a field in a generic type definition,
561 // a memberref token is returned (confirmed on .NET) unlike for Get(Method|Constructor)Token which always
562 // simply returns the MethodDef token (if the method is from the same module).
563 FieldBuilder fb = field as FieldBuilder;
564 if (fb != null && fb.Module == this && !IsFromGenericTypeDefinition(fb))
566 return new FieldToken(fb.MetadataToken);
570 return new FieldToken(ImportMember(field));
574 public MethodToken GetMethodToken(MethodInfo method)
576 MethodBuilder mb = method as MethodBuilder;
577 if (mb != null && mb.ModuleBuilder == this)
579 return new MethodToken(mb.MetadataToken);
583 return new MethodToken(ImportMember(method));
588 public MethodToken GetMethodToken(MethodInfo method, IEnumerable<Type> optionalParameterTypes)
590 return __GetMethodToken(method, Util.ToArray(optionalParameterTypes), null);
593 public MethodToken __GetMethodToken(MethodInfo method, Type[] optionalParameterTypes, CustomModifiers[] customModifiers)
595 ByteBuffer sig = new ByteBuffer(16);
596 method.MethodSignature.WriteMethodRefSig(this, sig, optionalParameterTypes, customModifiers);
597 MemberRefTable.Record record = new MemberRefTable.Record();
598 if (method.Module == this)
600 record.Class = method.MetadataToken;
604 record.Class = GetTypeTokenForMemberRef(method.DeclaringType ?? method.Module.GetModuleType());
606 record.Name = Strings.Add(method.Name);
607 record.Signature = Blobs.Add(sig);
608 return new MethodToken(0x0A000000 | MemberRef.FindOrAddRecord(record));
611 // when we refer to a method on a generic type definition in the IL stream,
612 // we need to use a MemberRef (even if the method is in the same module)
613 internal MethodToken GetMethodTokenForIL(MethodInfo method)
615 if (method.IsGenericMethodDefinition)
617 method = method.MakeGenericMethod(method.GetGenericArguments());
619 if (IsFromGenericTypeDefinition(method))
621 return new MethodToken(ImportMember(method));
625 return GetMethodToken(method);
629 public MethodToken GetConstructorToken(ConstructorInfo constructor)
631 if (constructor.Module == this && constructor.GetMethodInfo() is MethodBuilder)
633 return new MethodToken(constructor.MetadataToken);
637 return new MethodToken(ImportMember(constructor));
642 public MethodToken GetConstructorToken(ConstructorInfo constructor, IEnumerable<Type> optionalParameterTypes)
644 return GetMethodToken(constructor.GetMethodInfo(), optionalParameterTypes);
647 public MethodToken __GetConstructorToken(ConstructorInfo constructor, Type[] optionalParameterTypes, CustomModifiers[] customModifiers)
649 return __GetMethodToken(constructor.GetMethodInfo(), optionalParameterTypes, customModifiers);
652 internal int ImportMember(MethodBase member)
655 if (!importedMembers.TryGetValue(member, out token))
657 token = member.ImportTo(this);
658 importedMembers.Add(member, token);
663 internal int ImportMember(FieldInfo member)
666 if (!importedMembers.TryGetValue(member, out token))
668 token = member.ImportTo(this);
669 importedMembers.Add(member, token);
674 internal int ImportMethodOrField(Type declaringType, string name, Signature sig)
677 if (!importedMemberRefs.TryGetValue(new MemberRefKey(declaringType, name, sig), out token))
679 MemberRefTable.Record rec = new MemberRefTable.Record();
680 rec.Class = GetTypeTokenForMemberRef(declaringType);
681 rec.Name = this.Strings.Add(name);
682 ByteBuffer bb = new ByteBuffer(16);
683 sig.WriteSig(this, bb);
684 rec.Signature = this.Blobs.Add(bb);
685 token = 0x0A000000 | this.MemberRef.AddRecord(rec);
686 importedMemberRefs.Add(new MemberRefKey(declaringType, name, sig), token);
691 internal int ImportType(Type type)
694 if (!typeTokens.TryGetValue(type, out token))
696 if (type.HasElementType || type.IsGenericTypeInstance || type.__IsFunctionPointer)
698 ByteBuffer spec = new ByteBuffer(5);
699 Signature.WriteTypeSpec(this, spec, type);
700 token = 0x1B000000 | this.TypeSpec.AddRecord(this.Blobs.Add(spec));
704 TypeRefTable.Record rec = new TypeRefTable.Record();
707 rec.ResolutionScope = GetTypeToken(type.DeclaringType).Token;
711 rec.ResolutionScope = ImportAssemblyRef(type.Assembly);
713 rec.TypeName = this.Strings.Add(type.__Name);
714 string ns = type.__Namespace;
715 rec.TypeNameSpace = ns == null ? 0 : this.Strings.Add(ns);
716 token = 0x01000000 | this.TypeRef.AddRecord(rec);
718 typeTokens.Add(type, token);
723 private int ImportAssemblyRef(Assembly asm)
726 if (!referencedAssemblies.TryGetValue(asm, out token))
728 // We can't write the AssemblyRef record here yet, because the identity of the assembly can still change
729 // (if it's an AssemblyBuilder).
730 token = AllocPseudoToken();
731 referencedAssemblies.Add(asm, token);
736 internal void FillAssemblyRefTable()
738 foreach (KeyValuePair<Assembly, int> kv in referencedAssemblies)
740 if (IsPseudoToken(kv.Value))
742 RegisterTokenFixup(kv.Value, FindOrAddAssemblyRef(kv.Key.GetName(), false));
747 private int FindOrAddAssemblyRef(AssemblyName name, bool alwaysAdd)
749 AssemblyRefTable.Record rec = new AssemblyRefTable.Record();
750 Version ver = name.Version ?? new Version(0, 0, 0, 0);
751 rec.MajorVersion = (ushort)ver.Major;
752 rec.MinorVersion = (ushort)ver.Minor;
753 rec.BuildNumber = (ushort)ver.Build;
754 rec.RevisionNumber = (ushort)ver.Revision;
755 rec.Flags = (int)(name.Flags & ~AssemblyNameFlags.PublicKey);
756 const AssemblyNameFlags afPA_Specified = (AssemblyNameFlags)0x0080;
757 const AssemblyNameFlags afPA_Mask = (AssemblyNameFlags)0x0070;
758 if ((name.RawFlags & afPA_Specified) != 0)
760 rec.Flags |= (int)(name.RawFlags & afPA_Mask);
762 byte[] publicKeyOrToken = null;
763 if (usePublicKeyAssemblyReference)
765 publicKeyOrToken = name.GetPublicKey();
767 if (publicKeyOrToken == null || publicKeyOrToken.Length == 0)
769 publicKeyOrToken = name.GetPublicKeyToken() ?? Empty<byte>.Array;
773 const int PublicKey = 0x0001;
774 rec.Flags |= PublicKey;
776 rec.PublicKeyOrToken = this.Blobs.Add(ByteBuffer.Wrap(publicKeyOrToken));
777 rec.Name = this.Strings.Add(name.Name);
778 rec.Culture = name.Culture == null ? 0 : this.Strings.Add(name.Culture);
779 if (name.hash != null)
781 rec.HashValue = this.Blobs.Add(ByteBuffer.Wrap(name.hash));
787 return 0x23000000 | (alwaysAdd ? this.AssemblyRef.AddRecord(rec) : this.AssemblyRef.FindOrAddRecord(rec));
790 internal void WriteSymbolTokenMap()
792 for (int i = 0; i < resolvedTokens.Count; i++)
794 int newToken = resolvedTokens[i];
795 // The symbol API doesn't support remapping arbitrary integers, the types have to be the same,
796 // so we copy the type from the newToken, because our pseudo tokens don't have a type.
797 // (see MethodToken.SymbolToken)
798 int oldToken = (i + 1) | (newToken & ~0xFFFFFF);
799 SymbolSupport.RemapToken(symbolWriter, oldToken, newToken);
803 internal void RegisterTokenFixup(int pseudoToken, int realToken)
805 int index = -(pseudoToken + 1);
806 while (resolvedTokens.Count <= index)
808 resolvedTokens.Add(0);
810 resolvedTokens[index] = realToken;
813 internal bool IsPseudoToken(int token)
818 internal int ResolvePseudoToken(int pseudoToken)
820 int index = -(pseudoToken + 1);
821 return resolvedTokens[index];
824 internal void ApplyUnmanagedExports(ImageFileMachine imageFileMachine)
826 if (unmanagedExports.Count != 0)
830 if (imageFileMachine == ImageFileMachine.I386)
840 List<MethodBuilder> methods = new List<MethodBuilder>();
841 for (int i = 0; i < unmanagedExports.Count; i++)
843 if (unmanagedExports[i].mb != null)
845 methods.Add(unmanagedExports[i].mb);
848 if (methods.Count != 0)
850 RelativeVirtualAddress rva = __AddVTableFixups(methods.ToArray(), type);
851 for (int i = 0; i < unmanagedExports.Count; i++)
853 if (unmanagedExports[i].mb != null)
855 UnmanagedExport exp = unmanagedExports[i];
856 exp.rva = new RelativeVirtualAddress(rva.initializedDataOffset + (uint)(methods.IndexOf(unmanagedExports[i].mb) * size));
857 unmanagedExports[i] = exp;
864 internal void FixupMethodBodyTokens()
866 int methodToken = 0x06000001;
867 int fieldToken = 0x04000001;
868 int parameterToken = 0x08000001;
869 foreach (TypeBuilder type in types)
871 type.ResolveMethodAndFieldTokens(ref methodToken, ref fieldToken, ref parameterToken);
873 foreach (int offset in tokenFixupOffsets)
875 methodBodies.Position = offset;
876 int pseudoToken = methodBodies.GetInt32AtCurrentPosition();
877 methodBodies.Write(ResolvePseudoToken(pseudoToken));
879 foreach (VTableFixups fixup in vtablefixups)
881 for (int i = 0; i < fixup.count; i++)
883 initializedData.Position = (int)fixup.initializedDataOffset + i * fixup.SlotWidth;
884 initializedData.Write(ResolvePseudoToken(initializedData.GetInt32AtCurrentPosition()));
889 private int GetHeaderLength()
896 4 + // ImageRuntimeVersion Length
897 StringToPaddedUTF8Length(asm.ImageRuntimeVersion) +
902 4 + // StringToPaddedUTF8Length("#~")
903 4 + // #Strings Offset
905 12 + // StringToPaddedUTF8Length("#Strings")
908 4 + // StringToPaddedUTF8Length("#US")
911 8 + // StringToPaddedUTF8Length("#GUID")
916 8 // StringToPaddedUTF8Length("#Blob")
920 internal int MetadataLength
924 return GetHeaderLength() + (Blobs.IsEmpty ? 0 : Blobs.Length) + Tables.Length + Strings.Length + UserStrings.Length + Guids.Length;
928 internal void WriteMetadata(MetadataWriter mw)
930 mw.Write(0x424A5342); // Signature ("BSJB")
931 mw.Write((ushort)1); // MajorVersion
932 mw.Write((ushort)1); // MinorVersion
933 mw.Write(0); // Reserved
934 byte[] version = StringToPaddedUTF8(asm.ImageRuntimeVersion);
935 mw.Write(version.Length); // Length
937 mw.Write((ushort)0); // Flags
938 // #Blob is the only optional heap
941 mw.Write((ushort)4); // Streams
945 mw.Write((ushort)5); // Streams
948 int offset = GetHeaderLength();
951 mw.Write(offset); // Offset
952 mw.Write(Tables.Length); // Size
953 mw.Write(StringToPaddedUTF8("#~"));
954 offset += Tables.Length;
956 mw.Write(offset); // Offset
957 mw.Write(Strings.Length); // Size
958 mw.Write(StringToPaddedUTF8("#Strings"));
959 offset += Strings.Length;
961 mw.Write(offset); // Offset
962 mw.Write(UserStrings.Length); // Size
963 mw.Write(StringToPaddedUTF8("#US"));
964 offset += UserStrings.Length;
966 mw.Write(offset); // Offset
967 mw.Write(Guids.Length); // Size
968 mw.Write(StringToPaddedUTF8("#GUID"));
969 offset += Guids.Length;
973 mw.Write(offset); // Offset
974 mw.Write(Blobs.Length); // Size
975 mw.Write(StringToPaddedUTF8("#Blob"));
980 UserStrings.Write(mw);
988 private static int StringToPaddedUTF8Length(string str)
990 return (System.Text.Encoding.UTF8.GetByteCount(str) + 4) & ~3;
993 private static byte[] StringToPaddedUTF8(string str)
995 byte[] buf = new byte[(System.Text.Encoding.UTF8.GetByteCount(str) + 4) & ~3];
996 System.Text.Encoding.UTF8.GetBytes(str, 0, str.Length, buf, 0);
1000 internal override void ExportTypes(int fileToken, ModuleBuilder manifestModule)
1002 manifestModule.ExportTypes(types.ToArray(), fileToken);
1005 internal void ExportTypes(Type[] types, int fileToken)
1007 Dictionary<Type, int> declaringTypes = new Dictionary<Type, int>();
1008 foreach (Type type in types)
1010 if (!type.IsModulePseudoType && IsVisible(type))
1012 ExportedTypeTable.Record rec = new ExportedTypeTable.Record();
1013 rec.Flags = (int)type.Attributes;
1014 // LAMESPEC ECMA says that TypeDefId is a row index, but it should be a token
1015 rec.TypeDefId = type.MetadataToken;
1016 rec.TypeName = this.Strings.Add(type.__Name);
1017 string ns = type.__Namespace;
1018 rec.TypeNamespace = ns == null ? 0 : this.Strings.Add(ns);
1021 rec.Implementation = declaringTypes[type.DeclaringType];
1025 rec.Implementation = fileToken;
1027 int exportTypeToken = 0x27000000 | this.ExportedType.AddRecord(rec);
1028 declaringTypes.Add(type, exportTypeToken);
1033 private static bool IsVisible(Type type)
1035 // NOTE this is not the same as Type.IsVisible, because that doesn't take into account family access
1036 return type.IsPublic || ((type.IsNestedFamily || type.IsNestedFamORAssem || type.IsNestedPublic) && IsVisible(type.DeclaringType));
1039 internal void AddConstant(int parentToken, object defaultValue)
1041 ConstantTable.Record rec = new ConstantTable.Record();
1042 rec.Parent = parentToken;
1043 ByteBuffer val = new ByteBuffer(16);
1044 if (defaultValue == null)
1046 rec.Type = Signature.ELEMENT_TYPE_CLASS;
1049 else if (defaultValue is bool)
1051 rec.Type = Signature.ELEMENT_TYPE_BOOLEAN;
1052 val.Write((bool)defaultValue ? (byte)1 : (byte)0);
1054 else if (defaultValue is char)
1056 rec.Type = Signature.ELEMENT_TYPE_CHAR;
1057 val.Write((char)defaultValue);
1059 else if (defaultValue is sbyte)
1061 rec.Type = Signature.ELEMENT_TYPE_I1;
1062 val.Write((sbyte)defaultValue);
1064 else if (defaultValue is byte)
1066 rec.Type = Signature.ELEMENT_TYPE_U1;
1067 val.Write((byte)defaultValue);
1069 else if (defaultValue is short)
1071 rec.Type = Signature.ELEMENT_TYPE_I2;
1072 val.Write((short)defaultValue);
1074 else if (defaultValue is ushort)
1076 rec.Type = Signature.ELEMENT_TYPE_U2;
1077 val.Write((ushort)defaultValue);
1079 else if (defaultValue is int)
1081 rec.Type = Signature.ELEMENT_TYPE_I4;
1082 val.Write((int)defaultValue);
1084 else if (defaultValue is uint)
1086 rec.Type = Signature.ELEMENT_TYPE_U4;
1087 val.Write((uint)defaultValue);
1089 else if (defaultValue is long)
1091 rec.Type = Signature.ELEMENT_TYPE_I8;
1092 val.Write((long)defaultValue);
1094 else if (defaultValue is ulong)
1096 rec.Type = Signature.ELEMENT_TYPE_U8;
1097 val.Write((ulong)defaultValue);
1099 else if (defaultValue is float)
1101 rec.Type = Signature.ELEMENT_TYPE_R4;
1102 val.Write((float)defaultValue);
1104 else if (defaultValue is double)
1106 rec.Type = Signature.ELEMENT_TYPE_R8;
1107 val.Write((double)defaultValue);
1109 else if (defaultValue is string)
1111 rec.Type = Signature.ELEMENT_TYPE_STRING;
1112 foreach (char c in (string)defaultValue)
1117 else if (defaultValue is DateTime)
1119 rec.Type = Signature.ELEMENT_TYPE_I8;
1120 val.Write(((DateTime)defaultValue).Ticks);
1124 throw new ArgumentException();
1126 rec.Value = this.Blobs.Add(val);
1127 this.Constant.AddRecord(rec);
1130 ModuleBuilder ITypeOwner.ModuleBuilder
1132 get { return this; }
1135 public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1137 if (genericTypeArguments != null || genericMethodArguments != null)
1139 throw new NotImplementedException();
1141 return types[(metadataToken & 0xFFFFFF) - 1];
1144 public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1146 if (genericTypeArguments != null || genericMethodArguments != null)
1148 throw new NotImplementedException();
1150 // this method is inefficient, but since it isn't used we don't care
1151 if ((metadataToken >> 24) == MemberRefTable.Index)
1153 foreach (KeyValuePair<MemberInfo, int> kv in importedMembers)
1155 if (kv.Value == metadataToken)
1157 return (MethodBase)kv.Key;
1161 // HACK if we're given a SymbolToken, we need to convert back
1162 if ((metadataToken & 0xFF000000) == 0x06000000)
1164 metadataToken = -(metadataToken & 0x00FFFFFF);
1166 foreach (Type type in types)
1168 MethodBase method = ((TypeBuilder)type).LookupMethod(metadataToken);
1174 return ((TypeBuilder)moduleType).LookupMethod(metadataToken);
1177 public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1179 throw new NotImplementedException();
1182 public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1184 throw new NotImplementedException();
1187 public override string ResolveString(int metadataToken)
1189 throw new NotImplementedException();
1192 public override string FullyQualifiedName
1194 get { return Path.GetFullPath(Path.Combine(asm.dir, fileName)); }
1197 public override string Name
1199 get { return fileName; }
1202 public override Guid ModuleVersionId
1204 get { return mvid; }
1207 public void __SetModuleVersionId(Guid guid)
1212 public override Type[] __ResolveOptionalParameterTypes(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments, out CustomModifiers[] customModifiers)
1214 throw new NotImplementedException();
1217 public override string ScopeName
1219 get { return moduleName; }
1222 public ISymbolWriter GetSymWriter()
1224 return symbolWriter;
1227 public void DefineUnmanagedResource(string resourceFileName)
1229 // This method reads the specified resource file (Win32 .res file) and converts it into the appropriate format and embeds it in the .rsrc section,
1230 // also setting the Resource Directory entry.
1231 unmanagedResources = new ResourceSection();
1232 unmanagedResources.ExtractResources(System.IO.File.ReadAllBytes(resourceFileName));
1235 public bool IsTransient()
1240 public void SetUserEntryPoint(MethodInfo entryPoint)
1242 int token = entryPoint.MetadataToken;
1245 token = -token | 0x06000000;
1247 if (symbolWriter != null)
1249 symbolWriter.SetUserEntryPoint(new SymbolToken(token));
1253 public StringToken GetStringConstant(string str)
1255 return new StringToken(this.UserStrings.Add(str) | (0x70 << 24));
1258 public SignatureToken GetSignatureToken(SignatureHelper sigHelper)
1260 return new SignatureToken(this.StandAloneSig.FindOrAddRecord(this.Blobs.Add(sigHelper.GetSignature(this))) | (StandAloneSigTable.Index << 24));
1263 public SignatureToken GetSignatureToken(byte[] sigBytes, int sigLength)
1265 return new SignatureToken(this.StandAloneSig.FindOrAddRecord(this.Blobs.Add(ByteBuffer.Wrap(sigBytes, sigLength))) | (StandAloneSigTable.Index << 24));
1268 public MethodInfo GetArrayMethod(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
1270 return new ArrayMethod(this, arrayClass, methodName, callingConvention, returnType, parameterTypes);
1273 public MethodToken GetArrayMethodToken(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
1275 return GetMethodToken(GetArrayMethod(arrayClass, methodName, callingConvention, returnType, parameterTypes));
1278 internal override Type GetModuleType()
1283 internal override IKVM.Reflection.Reader.ByteReader GetBlob(int blobIndex)
1285 return Blobs.GetBlob(blobIndex);
1288 internal int GetSignatureBlobIndex(Signature sig)
1290 ByteBuffer bb = new ByteBuffer(16);
1291 sig.WriteSig(this, bb);
1292 return this.Blobs.Add(bb);
1296 public new long __ImageBase
1298 get { return imageBaseAddress; }
1299 set { imageBaseAddress = value; }
1302 protected override long GetImageBaseImpl()
1304 return imageBaseAddress;
1307 public new long __StackReserve
1309 get { return stackReserve; }
1310 set { stackReserve = value; }
1313 protected override long GetStackReserveImpl()
1315 return stackReserve;
1318 [Obsolete("Use __StackReserve property.")]
1319 public void __SetStackReserve(long stackReserve)
1321 __StackReserve = stackReserve;
1324 internal ulong GetStackReserve(ulong defaultValue)
1326 return stackReserve == -1 ? defaultValue : (ulong)stackReserve;
1329 public new int __FileAlignment
1331 get { return fileAlignment; }
1332 set { fileAlignment = value; }
1335 protected override int GetFileAlignmentImpl()
1337 return fileAlignment;
1340 public new DllCharacteristics __DllCharacteristics
1342 get { return dllCharacteristics; }
1343 set { dllCharacteristics = value; }
1346 protected override DllCharacteristics GetDllCharacteristicsImpl()
1348 return dllCharacteristics;
1351 public override int MDStreamVersion
1353 get { return asm.mdStreamVersion; }
1356 private int AddTypeRefByName(int resolutionScope, string ns, string name)
1358 TypeRefTable.Record rec = new TypeRefTable.Record();
1359 rec.ResolutionScope = resolutionScope;
1360 rec.TypeName = this.Strings.Add(name);
1361 rec.TypeNameSpace = ns == null ? 0 : this.Strings.Add(ns);
1362 return 0x01000000 | this.TypeRef.AddRecord(rec);
1365 public void __Save(PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1367 SaveImpl(null, portableExecutableKind, imageFileMachine);
1370 public void __Save(Stream stream, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1372 if (!stream.CanRead || !stream.CanWrite || !stream.CanSeek || stream.Position != 0)
1374 throw new ArgumentException("Stream must support read/write/seek and current position must be zero.", "stream");
1376 SaveImpl(stream, portableExecutableKind, imageFileMachine);
1379 private void SaveImpl(Stream streamOrNull, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1381 PopulatePropertyAndEventTables();
1382 IList<CustomAttributeData> attributes = asm.GetCustomAttributesData(null);
1383 if (attributes.Count > 0)
1385 int mscorlib = ImportAssemblyRef(universe.Mscorlib);
1386 int[] placeholderTokens = new int[4];
1387 string[] placeholderTypeNames = new string[] { "AssemblyAttributesGoHere", "AssemblyAttributesGoHereM", "AssemblyAttributesGoHereS", "AssemblyAttributesGoHereSM" };
1388 foreach (CustomAttributeData cad in attributes)
1391 if (cad.Constructor.DeclaringType.BaseType == universe.System_Security_Permissions_CodeAccessSecurityAttribute)
1393 if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute)
1402 else if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute)
1410 if (placeholderTokens[index] == 0)
1412 // we manually add a TypeRef without looking it up in mscorlib, because Mono and Silverlight's mscorlib don't have these types
1413 placeholderTokens[index] = AddTypeRefByName(mscorlib, "System.Runtime.CompilerServices", placeholderTypeNames[index]);
1415 SetCustomAttribute(placeholderTokens[index], cad.__ToBuilder());
1418 FillAssemblyRefTable();
1419 ModuleWriter.WriteModule(null, null, this, PEFileKinds.Dll, portableExecutableKind, imageFileMachine, unmanagedResources, 0, streamOrNull);
1422 public void __AddAssemblyReference(AssemblyName assemblyName)
1424 __AddAssemblyReference(assemblyName, null);
1427 public void __AddAssemblyReference(AssemblyName assemblyName, Assembly assembly)
1429 if (referencedAssemblyNames == null)
1431 referencedAssemblyNames = new List<AssemblyName>();
1433 referencedAssemblyNames.Add((AssemblyName)assemblyName.Clone());
1434 int token = FindOrAddAssemblyRef(assemblyName, true);
1435 if (assembly != null)
1437 referencedAssemblies.Add(assembly, token);
1441 public override AssemblyName[] __GetReferencedAssemblies()
1443 List<AssemblyName> list = new List<AssemblyName>();
1444 if (referencedAssemblyNames != null)
1446 foreach (AssemblyName name in referencedAssemblyNames)
1448 if (!list.Contains(name))
1454 foreach (Assembly asm in referencedAssemblies.Keys)
1456 AssemblyName name = asm.GetName();
1457 if (!list.Contains(name))
1462 return list.ToArray();
1465 public void __AddModuleReference(string module)
1467 this.ModuleRef.FindOrAddRecord(module == null ? 0 : this.Strings.Add(module));
1470 public override string[] __GetReferencedModules()
1472 string[] arr = new string[this.ModuleRef.RowCount];
1473 for (int i = 0; i < arr.Length; i++)
1475 arr[i] = this.Strings.Find(this.ModuleRef.records[i]);
1480 public override Type[] __GetReferencedTypes()
1482 List<Type> list = new List<Type>();
1483 foreach (KeyValuePair<Type, int> kv in typeTokens)
1485 if (kv.Value >> 24 == TypeRefTable.Index)
1490 return list.ToArray();
1493 public override Type[] __GetExportedTypes()
1495 throw new NotImplementedException();
1498 public int __AddModule(int flags, string name, byte[] hash)
1500 FileTable.Record file = new FileTable.Record();
1502 file.Name = this.Strings.Add(name);
1503 file.HashValue = this.Blobs.Add(ByteBuffer.Wrap(hash));
1504 return 0x26000000 + this.File.AddRecord(file);
1507 public int __AddManifestResource(int offset, ResourceAttributes flags, string name, int implementation)
1509 ManifestResourceTable.Record res = new ManifestResourceTable.Record();
1510 res.Offset = offset;
1511 res.Flags = (int)flags;
1512 res.Name = this.Strings.Add(name);
1513 res.Implementation = implementation;
1514 return 0x28000000 + this.ManifestResource.AddRecord(res);
1517 public void __SetCustomAttributeFor(int token, CustomAttributeBuilder customBuilder)
1519 SetCustomAttribute(token, customBuilder);
1522 public RelativeVirtualAddress __AddVTableFixups(MethodBuilder[] methods, int type)
1524 initializedData.Align(8);
1525 VTableFixups fixups;
1526 fixups.initializedDataOffset = (uint)initializedData.Position;
1527 fixups.count = (ushort)methods.Length;
1528 fixups.type = (ushort)type;
1529 foreach (MethodBuilder mb in methods)
1531 initializedData.Write(mb.MetadataToken);
1532 if (fixups.SlotWidth == 8)
1534 initializedData.Write(0);
1537 vtablefixups.Add(fixups);
1538 return new RelativeVirtualAddress(fixups.initializedDataOffset);
1541 public void __AddUnmanagedExportStub(string name, int ordinal, RelativeVirtualAddress rva)
1543 AddUnmanagedExport(name, ordinal, null, rva);
1546 internal void AddUnmanagedExport(string name, int ordinal, MethodBuilder methodBuilder, RelativeVirtualAddress rva)
1548 UnmanagedExport export;
1550 export.ordinal = ordinal;
1551 export.mb = methodBuilder;
1553 unmanagedExports.Add(export);
1556 internal void SetInterfaceImplementationCustomAttribute(TypeBuilder typeBuilder, Type interfaceType, CustomAttributeBuilder cab)
1558 // NOTE since interfaceimpls are extremely common and custom attributes on them are extremely rare,
1559 // we store (and resolve) the custom attributes in such away as to avoid impacting the common case performance
1560 if (interfaceImplCustomAttributes == null)
1562 interfaceImplCustomAttributes = new List<InterfaceImplCustomAttribute>();
1564 InterfaceImplCustomAttribute rec;
1565 rec.type = typeBuilder.MetadataToken;
1566 int token = GetTypeToken(interfaceType).Token;
1567 switch (token >> 24)
1569 case TypeDefTable.Index:
1570 token = (token & 0xFFFFFF) << 2 | 0;
1572 case TypeRefTable.Index:
1573 token = (token & 0xFFFFFF) << 2 | 1;
1575 case TypeSpecTable.Index:
1576 token = (token & 0xFFFFFF) << 2 | 2;
1579 throw new InvalidOperationException();
1581 rec.interfaceType = token;
1582 rec.pseudoToken = AllocPseudoToken();
1583 interfaceImplCustomAttributes.Add(rec);
1584 SetCustomAttribute(rec.pseudoToken, cab);
1587 internal void ResolveInterfaceImplPseudoTokens()
1589 if (interfaceImplCustomAttributes != null)
1591 foreach (InterfaceImplCustomAttribute rec in interfaceImplCustomAttributes)
1593 for (int i = 0; i < InterfaceImpl.records.Length; i++)
1595 if (InterfaceImpl.records[i].Class == rec.type && InterfaceImpl.records[i].Interface == rec.interfaceType)
1597 RegisterTokenFixup(rec.pseudoToken, (InterfaceImplTable.Index << 24) | (i + 1));
1605 internal void FixupPseudoToken(ref int token)
1607 if (IsPseudoToken(token))
1609 token = ResolvePseudoToken(token);
1614 struct UnmanagedExport
1616 internal string name;
1617 internal int ordinal;
1618 internal RelativeVirtualAddress rva;
1619 internal MethodBuilder mb;
1622 public struct RelativeVirtualAddress
1624 internal readonly uint initializedDataOffset;
1626 internal RelativeVirtualAddress(uint initializedDataOffset)
1628 this.initializedDataOffset = initializedDataOffset;
1631 public static RelativeVirtualAddress operator +(RelativeVirtualAddress rva, int offset)
1633 return new RelativeVirtualAddress(rva.initializedDataOffset + (uint)offset);
1637 class ArrayMethod : MethodInfo
1639 private readonly Module module;
1640 private readonly Type arrayClass;
1641 private readonly string methodName;
1642 private readonly CallingConventions callingConvention;
1643 private readonly Type returnType;
1644 protected readonly Type[] parameterTypes;
1645 private MethodSignature methodSignature;
1647 internal ArrayMethod(Module module, Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
1649 this.module = module;
1650 this.arrayClass = arrayClass;
1651 this.methodName = methodName;
1652 this.callingConvention = callingConvention;
1653 this.returnType = returnType ?? module.universe.System_Void;
1654 this.parameterTypes = Util.Copy(parameterTypes);
1657 public override MethodBody GetMethodBody()
1659 throw new InvalidOperationException();
1662 public override int __MethodRVA
1664 get { throw new InvalidOperationException(); }
1667 public override MethodImplAttributes GetMethodImplementationFlags()
1669 throw new NotSupportedException();
1672 public override ParameterInfo[] GetParameters()
1674 throw new NotSupportedException();
1677 internal override int ImportTo(ModuleBuilder module)
1679 return module.ImportMethodOrField(arrayClass, methodName, MethodSignature);
1682 public override MethodAttributes Attributes
1684 get { throw new NotSupportedException(); }
1687 public override CallingConventions CallingConvention
1689 get { return callingConvention; }
1692 public override Type DeclaringType
1694 get { return arrayClass; }
1697 internal override MethodSignature MethodSignature
1701 if (methodSignature == null)
1703 methodSignature = MethodSignature.MakeFromBuilder(returnType, parameterTypes, new PackedCustomModifiers(), callingConvention, 0);
1705 return methodSignature;
1709 public override Module Module
1711 // like .NET, we return the module that GetArrayMethod was called on, not the module associated with the array type
1712 get { return module; }
1715 public override string Name
1717 get { return methodName; }
1720 internal override int ParameterCount
1722 get { return parameterTypes.Length; }
1725 public override ParameterInfo ReturnParameter
1727 get { throw new NotImplementedException(); }
1730 public override Type ReturnType
1732 get { return returnType; }
1735 internal override bool HasThis
1737 get { return (callingConvention & (CallingConventions.HasThis | CallingConventions.ExplicitThis)) == CallingConventions.HasThis; }