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.Resources;
31
using System.Runtime.CompilerServices;
32
using System.Runtime.InteropServices;
33
using IKVM.Reflection.Impl;
34
using IKVM.Reflection.Metadata;
35
using IKVM.Reflection.Writer;
37
namespace IKVM.Reflection.Emit
39
public sealed class ModuleBuilder : Module, ITypeOwner
41
private static readonly bool usePublicKeyAssemblyReference = false;
42
private Guid mvid = Guid.NewGuid();
43
private long imageBaseAddress = 0x00400000;
44
private long stackReserve = -1;
45
private int fileAlignment = 0x200;
46
private DllCharacteristics dllCharacteristics = DllCharacteristics.DynamicBase | DllCharacteristics.NoSEH | DllCharacteristics.NXCompat | DllCharacteristics.TerminalServerAware;
47
private readonly AssemblyBuilder asm;
48
internal readonly string moduleName;
49
internal readonly string fileName;
50
internal readonly ISymbolWriterImpl symbolWriter;
51
private readonly TypeBuilder moduleType;
52
private readonly List<TypeBuilder> types = new List<TypeBuilder>();
53
private readonly Dictionary<Type, int> typeTokens = new Dictionary<Type, int>();
54
private readonly Dictionary<Type, int> memberRefTypeTokens = new Dictionary<Type, int>();
55
internal readonly ByteBuffer methodBodies = new ByteBuffer(128 * 1024);
56
internal readonly List<int> tokenFixupOffsets = new List<int>();
57
internal readonly ByteBuffer initializedData = new ByteBuffer(512);
58
internal readonly ByteBuffer manifestResources = new ByteBuffer(512);
59
internal ResourceSection unmanagedResources;
60
private readonly Dictionary<MemberRefKey, int> importedMemberRefs = new Dictionary<MemberRefKey, int>();
61
private readonly Dictionary<MethodSpecKey, int> importedMethodSpecs = new Dictionary<MethodSpecKey, int>();
62
private readonly Dictionary<Assembly, int> referencedAssemblies = new Dictionary<Assembly, int>();
63
private List<AssemblyName> referencedAssemblyNames;
64
private int nextPseudoToken = -1;
65
private readonly List<int> resolvedTokens = new List<int>();
66
internal readonly TableHeap Tables = new TableHeap();
67
internal readonly StringHeap Strings = new StringHeap();
68
internal readonly UserStringHeap UserStrings = new UserStringHeap();
69
internal readonly GuidHeap Guids = new GuidHeap();
70
internal readonly BlobHeap Blobs = new BlobHeap();
71
internal readonly List<VTableFixups> vtablefixups = new List<VTableFixups>();
72
internal readonly List<UnmanagedExport> unmanagedExports = new List<UnmanagedExport>();
73
private List<InterfaceImplCustomAttribute> interfaceImplCustomAttributes;
74
private List<ResourceWriterRecord> resourceWriters;
77
private struct ResourceWriterRecord
79
private readonly string name;
80
private readonly ResourceWriter rw;
81
private readonly MemoryStream mem;
82
private readonly ResourceAttributes attributes;
84
internal ResourceWriterRecord(string name, ResourceWriter rw, MemoryStream mem, ResourceAttributes attributes)
89
this.attributes = attributes;
92
internal void Emit(ModuleBuilder mb)
96
mb.DefineManifestResource(name, mem, attributes);
101
internal struct VTableFixups
103
internal uint initializedDataOffset;
104
internal ushort count;
105
internal ushort type;
107
internal int SlotWidth
109
get { return (type & 0x02) == 0 ? 4 : 8; }
113
struct InterfaceImplCustomAttribute
116
internal int interfaceType;
117
internal int pseudoToken;
120
struct MemberRefKey : IEquatable<MemberRefKey>
122
private readonly Type type;
123
private readonly string name;
124
private readonly Signature signature;
126
internal MemberRefKey(Type type, string name, Signature signature)
130
this.signature = signature;
133
public bool Equals(MemberRefKey other)
135
return other.type.Equals(type)
136
&& other.name == name
137
&& other.signature.Equals(signature);
140
public override bool Equals(object obj)
142
MemberRefKey? other = obj as MemberRefKey?;
143
return other != null && Equals(other);
146
public override int GetHashCode()
148
return type.GetHashCode() + name.GetHashCode() + signature.GetHashCode();
151
internal MethodBase LookupMethod()
153
return type.FindMethod(name, (MethodSignature)signature);
157
struct MethodSpecKey : IEquatable<MethodSpecKey>
159
private readonly Type type;
160
private readonly string name;
161
private readonly MethodSignature signature;
162
private readonly Type[] genericParameters;
164
internal MethodSpecKey(Type type, string name, MethodSignature signature, Type[] genericParameters)
168
this.signature = signature;
169
this.genericParameters = genericParameters;
172
public bool Equals(MethodSpecKey other)
174
return other.type.Equals(type)
175
&& other.name == name
176
&& other.signature.Equals(signature)
177
&& Util.ArrayEquals(other.genericParameters, genericParameters);
180
public override bool Equals(object obj)
182
MethodSpecKey? other = obj as MethodSpecKey?;
183
return other != null && Equals(other);
186
public override int GetHashCode()
188
return type.GetHashCode() + name.GetHashCode() + signature.GetHashCode() + Util.GetHashCode(genericParameters);
192
internal ModuleBuilder(AssemblyBuilder asm, string moduleName, string fileName, bool emitSymbolInfo)
196
this.moduleName = moduleName;
197
this.fileName = fileName;
200
symbolWriter = SymbolSupport.CreateSymbolWriterFor(this);
202
// <Module> must be the first record in the TypeDef table
203
moduleType = new TypeBuilder(this, null, "<Module>");
204
types.Add(moduleType);
207
internal void PopulatePropertyAndEventTables()
209
// LAMESPEC the PropertyMap and EventMap tables are not required to be sorted by the CLI spec,
210
// but .NET sorts them and Mono requires them to be sorted, so we have to populate the
211
// tables in the right order
212
foreach (TypeBuilder type in types)
214
type.PopulatePropertyAndEventTables();
218
internal void WriteTypeDefTable(MetadataWriter mw)
222
foreach (TypeBuilder type in types)
224
type.WriteTypeDefRecord(mw, ref fieldList, ref methodList);
228
internal void WriteMethodDefTable(int baseRVA, MetadataWriter mw)
231
foreach (TypeBuilder type in types)
233
type.WriteMethodDefRecords(baseRVA, mw, ref paramList);
237
internal void WriteParamTable(MetadataWriter mw)
239
foreach (TypeBuilder type in types)
241
type.WriteParamRecords(mw);
245
internal void WriteFieldTable(MetadataWriter mw)
247
foreach (TypeBuilder type in types)
249
type.WriteFieldRecords(mw);
253
internal int AllocPseudoToken()
255
return nextPseudoToken--;
258
public TypeBuilder DefineType(string name)
260
return DefineType(name, TypeAttributes.Class);
263
public TypeBuilder DefineType(string name, TypeAttributes attr)
265
return DefineType(name, attr, null);
268
public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent)
270
return DefineType(name, attr, parent, PackingSize.Unspecified, 0);
273
public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, int typesize)
275
return DefineType(name, attr, parent, PackingSize.Unspecified, typesize);
278
public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packsize)
280
return DefineType(name, attr, parent, packsize, 0);
283
public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, Type[] interfaces)
285
TypeBuilder tb = DefineType(name, attr, parent);
286
foreach (Type iface in interfaces)
288
tb.AddInterfaceImplementation(iface);
293
public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize)
296
int lastdot = name.LastIndexOf('.');
299
ns = name.Substring(0, lastdot);
300
name = name.Substring(lastdot + 1);
302
TypeBuilder typeBuilder = __DefineType(ns, name);
303
typeBuilder.__SetAttributes(attr);
304
typeBuilder.SetParent(parent);
305
if (packingSize != PackingSize.Unspecified || typesize != 0)
307
typeBuilder.__SetLayout((int)packingSize, typesize);
312
public TypeBuilder __DefineType(string ns, string name)
314
return DefineType(this, ns, name);
317
internal TypeBuilder DefineType(ITypeOwner owner, string ns, string name)
319
TypeBuilder typeBuilder = new TypeBuilder(owner, ns, name);
320
types.Add(typeBuilder);
324
public EnumBuilder DefineEnum(string name, TypeAttributes visibility, Type underlyingType)
326
TypeBuilder tb = DefineType(name, (visibility & TypeAttributes.VisibilityMask) | TypeAttributes.Sealed, universe.System_Enum);
327
FieldBuilder fb = tb.DefineField("value__", underlyingType, FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
328
return new EnumBuilder(tb, fb);
331
public FieldBuilder __DefineField(string name, Type type, CustomModifiers customModifiers, FieldAttributes attributes)
333
return moduleType.__DefineField(name, type, customModifiers, attributes);
336
[Obsolete("Please use __DefineField(string, Type, CustomModifiers, FieldAttributes) instead.")]
337
public FieldBuilder __DefineField(string name, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes)
339
return moduleType.DefineField(name, type, requiredCustomModifiers, optionalCustomModifiers, attributes);
342
public ConstructorBuilder __DefineModuleInitializer(MethodAttributes visibility)
344
return moduleType.DefineConstructor(visibility | MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, Type.EmptyTypes);
347
public FieldBuilder DefineUninitializedData(string name, int size, FieldAttributes attributes)
349
return moduleType.DefineUninitializedData(name, size, attributes);
352
public FieldBuilder DefineInitializedData(string name, byte[] data, FieldAttributes attributes)
354
return moduleType.DefineInitializedData(name, data, attributes);
357
public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)
359
return moduleType.DefineMethod(name, attributes, returnType, parameterTypes);
362
public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
364
return moduleType.DefineMethod(name, attributes, callingConvention, returnType, parameterTypes);
367
public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
369
return moduleType.DefineMethod(name, attributes, callingConvention, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
372
public MethodBuilder DefinePInvokeMethod(string name, string dllName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
374
return moduleType.DefinePInvokeMethod(name, dllName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
377
public MethodBuilder DefinePInvokeMethod(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
379
return moduleType.DefinePInvokeMethod(name, dllName, entryName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
382
public void CreateGlobalFunctions()
384
moduleType.CreateType();
387
internal void AddTypeForwarder(Type type)
390
if (!type.__IsMissing)
392
foreach (Type nested in type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic))
394
// we export all nested types (i.e. even the private ones)
395
// (this behavior is the same as the C# compiler)
396
AddTypeForwarder(nested);
401
private int ExportType(Type type)
403
ExportedTypeTable.Record rec = new ExportedTypeTable.Record();
404
rec.TypeName = this.Strings.Add(type.__Name);
405
string ns = type.__Namespace;
406
rec.TypeNamespace = ns == null ? 0 : this.Strings.Add(ns);
410
rec.Implementation = ExportType(type.DeclaringType);
414
rec.Flags = 0x00200000; // CorTypeAttr.tdForwarder
415
rec.Implementation = ImportAssemblyRef(type.Assembly);
417
return 0x27000000 | this.ExportedType.FindOrAddRecord(rec);
420
public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
422
SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
425
public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
427
SetCustomAttribute(0x00000001, customBuilder);
430
internal void SetCustomAttribute(int token, CustomAttributeBuilder customBuilder)
432
Debug.Assert(!customBuilder.IsPseudoCustomAttribute);
433
CustomAttributeTable.Record rec = new CustomAttributeTable.Record();
435
rec.Type = asm.IsWindowsRuntime ? customBuilder.Constructor.ImportTo(this) : GetConstructorToken(customBuilder.Constructor).Token;
436
rec.Value = customBuilder.WriteBlob(this);
437
this.CustomAttribute.AddRecord(rec);
440
internal void AddDeclarativeSecurity(int token, System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet)
442
DeclSecurityTable.Record rec = new DeclSecurityTable.Record();
443
rec.Action = (short)securityAction;
445
// like Ref.Emit, we're using the .NET 1.x xml format
446
rec.PermissionSet = this.Blobs.Add(ByteBuffer.Wrap(System.Text.Encoding.Unicode.GetBytes(permissionSet.ToXml().ToString())));
447
this.DeclSecurity.AddRecord(rec);
450
internal void AddDeclarativeSecurity(int token, List<CustomAttributeBuilder> declarativeSecurity)
452
Dictionary<int, List<CustomAttributeBuilder>> ordered = new Dictionary<int, List<CustomAttributeBuilder>>();
453
foreach (CustomAttributeBuilder cab in declarativeSecurity)
456
// check for HostProtectionAttribute without SecurityAction
457
if (cab.ConstructorArgumentCount == 0)
459
action = (int)System.Security.Permissions.SecurityAction.LinkDemand;
463
action = (int)cab.GetConstructorArgument(0);
465
List<CustomAttributeBuilder> list;
466
if (!ordered.TryGetValue(action, out list))
468
list = new List<CustomAttributeBuilder>();
469
ordered.Add(action, list);
473
foreach (KeyValuePair<int, List<CustomAttributeBuilder>> kv in ordered)
475
DeclSecurityTable.Record rec = new DeclSecurityTable.Record();
476
rec.Action = (short)kv.Key;
478
rec.PermissionSet = WriteDeclSecurityBlob(kv.Value);
479
this.DeclSecurity.AddRecord(rec);
483
private int WriteDeclSecurityBlob(List<CustomAttributeBuilder> list)
486
if (list.Count == 1 && (xml = list[0].GetLegacyDeclSecurity()) != null)
488
// write .NET 1.1 format
489
return this.Blobs.Add(ByteBuffer.Wrap(System.Text.Encoding.Unicode.GetBytes(xml)));
491
ByteBuffer namedArgs = new ByteBuffer(100);
492
ByteBuffer bb = new ByteBuffer(list.Count * 100);
494
bb.WriteCompressedUInt(list.Count);
495
foreach (CustomAttributeBuilder cab in list)
497
bb.Write(cab.Constructor.DeclaringType.AssemblyQualifiedName);
499
cab.WriteNamedArgumentsForDeclSecurity(this, namedArgs);
500
bb.WriteCompressedUInt(namedArgs.Length);
503
return this.Blobs.Add(bb);
506
public void DefineManifestResource(string name, Stream stream, ResourceAttributes attribute)
508
manifestResources.Align(8);
509
ManifestResourceTable.Record rec = new ManifestResourceTable.Record();
510
rec.Offset = manifestResources.Position;
511
rec.Flags = (int)attribute;
512
rec.Name = this.Strings.Add(name);
513
rec.Implementation = 0;
514
this.ManifestResource.AddRecord(rec);
515
manifestResources.Write(0); // placeholder for the length
516
manifestResources.Write(stream);
517
int savePosition = manifestResources.Position;
518
manifestResources.Position = rec.Offset;
519
manifestResources.Write(savePosition - (manifestResources.Position + 4));
520
manifestResources.Position = savePosition;
523
public IResourceWriter DefineResource(string name, string description)
525
return DefineResource(name, description, ResourceAttributes.Public);
528
public IResourceWriter DefineResource(string name, string description, ResourceAttributes attribute)
530
// FXBUG we ignore the description, because there is no such thing
532
if (resourceWriters == null)
534
resourceWriters = new List<ResourceWriterRecord>();
536
MemoryStream mem = new MemoryStream();
537
ResourceWriter rw = new ResourceWriter(mem);
538
resourceWriters.Add(new ResourceWriterRecord(name, rw, mem, attribute));
542
internal void EmitResources()
544
if (resourceWriters != null)
546
foreach (ResourceWriterRecord rwr in resourceWriters)
553
public override Assembly Assembly
558
internal override Type FindType(TypeName name)
560
foreach (Type type in types)
562
if (type.__Namespace == name.Namespace && type.__Name == name.Name)
570
internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
572
foreach (Type type in types)
574
if (new TypeName(type.__Namespace, type.__Name).ToLowerInvariant() == lowerCaseName)
582
internal override void GetTypesImpl(List<Type> list)
584
foreach (Type type in types)
586
if (type != moduleType)
593
public ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType)
595
return symbolWriter.DefineDocument(url, language, languageVendor, documentType);
598
public int __GetAssemblyToken(Assembly assembly)
600
return ImportAssemblyRef(assembly);
603
public TypeToken GetTypeToken(string name)
605
return new TypeToken(GetType(name, true, false).MetadataToken);
608
public TypeToken GetTypeToken(Type type)
610
if (type.Module == this && !asm.IsWindowsRuntime)
612
return new TypeToken(type.GetModuleBuilderToken());
616
return new TypeToken(ImportType(type));
620
internal int GetTypeTokenForMemberRef(Type type)
622
if (type.__IsMissing)
624
return ImportType(type);
626
else if (type.IsGenericTypeDefinition)
629
if (!memberRefTypeTokens.TryGetValue(type, out token))
631
ByteBuffer spec = new ByteBuffer(5);
632
Signature.WriteTypeSpec(this, spec, type);
633
token = 0x1B000000 | this.TypeSpec.AddRecord(this.Blobs.Add(spec));
634
memberRefTypeTokens.Add(type, token);
638
else if (type.IsModulePseudoType)
640
return 0x1A000000 | this.ModuleRef.FindOrAddRecord(this.Strings.Add(type.Module.ScopeName));
644
return GetTypeToken(type).Token;
648
private static bool IsFromGenericTypeDefinition(MemberInfo member)
650
Type decl = member.DeclaringType;
651
return decl != null && !decl.__IsMissing && decl.IsGenericTypeDefinition;
654
public FieldToken GetFieldToken(FieldInfo field)
656
// NOTE for some reason, when TypeBuilder.GetFieldToken() is used on a field in a generic type definition,
657
// a memberref token is returned (confirmed on .NET) unlike for Get(Method|Constructor)Token which always
658
// simply returns the MethodDef token (if the method is from the same module).
659
FieldBuilder fb = field as FieldBuilder;
660
if (fb != null && fb.Module == this && !IsFromGenericTypeDefinition(fb))
662
return new FieldToken(fb.MetadataToken);
666
return new FieldToken(field.ImportTo(this));
670
public MethodToken GetMethodToken(MethodInfo method)
672
MethodBuilder mb = method as MethodBuilder;
673
if (mb != null && mb.ModuleBuilder == this)
675
return new MethodToken(mb.MetadataToken);
679
return new MethodToken(method.ImportTo(this));
684
public MethodToken GetMethodToken(MethodInfo method, IEnumerable<Type> optionalParameterTypes)
686
return __GetMethodToken(method, Util.ToArray(optionalParameterTypes), null);
689
public MethodToken __GetMethodToken(MethodInfo method, Type[] optionalParameterTypes, CustomModifiers[] customModifiers)
691
ByteBuffer sig = new ByteBuffer(16);
692
method.MethodSignature.WriteMethodRefSig(this, sig, optionalParameterTypes, customModifiers);
693
MemberRefTable.Record record = new MemberRefTable.Record();
694
if (method.Module == this)
696
record.Class = method.MetadataToken;
700
record.Class = GetTypeTokenForMemberRef(method.DeclaringType ?? method.Module.GetModuleType());
702
record.Name = Strings.Add(method.Name);
703
record.Signature = Blobs.Add(sig);
704
return new MethodToken(0x0A000000 | MemberRef.FindOrAddRecord(record));
707
// when we refer to a method on a generic type definition in the IL stream,
708
// we need to use a MemberRef (even if the method is in the same module)
709
internal MethodToken GetMethodTokenForIL(MethodInfo method)
711
if (method.IsGenericMethodDefinition)
713
method = method.MakeGenericMethod(method.GetGenericArguments());
715
if (IsFromGenericTypeDefinition(method))
717
return new MethodToken(method.ImportTo(this));
721
return GetMethodToken(method);
725
internal int GetMethodTokenWinRT(MethodInfo method)
727
return asm.IsWindowsRuntime ? method.ImportTo(this) : GetMethodToken(method).Token;
730
public MethodToken GetConstructorToken(ConstructorInfo constructor)
732
return GetMethodToken(constructor.GetMethodInfo());
736
public MethodToken GetConstructorToken(ConstructorInfo constructor, IEnumerable<Type> optionalParameterTypes)
738
return GetMethodToken(constructor.GetMethodInfo(), optionalParameterTypes);
741
public MethodToken __GetConstructorToken(ConstructorInfo constructor, Type[] optionalParameterTypes, CustomModifiers[] customModifiers)
743
return __GetMethodToken(constructor.GetMethodInfo(), optionalParameterTypes, customModifiers);
746
internal int ImportMethodOrField(Type declaringType, string name, Signature sig)
749
MemberRefKey key = new MemberRefKey(declaringType, name, sig);
750
if (!importedMemberRefs.TryGetValue(key, out token))
752
MemberRefTable.Record rec = new MemberRefTable.Record();
753
rec.Class = GetTypeTokenForMemberRef(declaringType);
754
rec.Name = this.Strings.Add(name);
755
ByteBuffer bb = new ByteBuffer(16);
756
sig.WriteSig(this, bb);
757
rec.Signature = this.Blobs.Add(bb);
758
token = 0x0A000000 | this.MemberRef.AddRecord(rec);
759
importedMemberRefs.Add(key, token);
764
internal int ImportMethodSpec(Type declaringType, MethodInfo method, Type[] genericParameters)
766
Debug.Assert(method.__IsMissing || method.GetMethodOnTypeDefinition() == method);
768
MethodSpecKey key = new MethodSpecKey(declaringType, method.Name, method.MethodSignature, genericParameters);
769
if (!importedMethodSpecs.TryGetValue(key, out token))
771
MethodSpecTable.Record rec = new MethodSpecTable.Record();
772
MethodBuilder mb = method as MethodBuilder;
773
if (mb != null && mb.ModuleBuilder == this && !declaringType.IsGenericType)
775
rec.Method = mb.MetadataToken;
779
// we're calling ImportMethodOrField directly here, because 'method' may be a MethodDef on a generic TypeDef and 'declaringType' the type instance
780
// (in order words the method and type have already been decoupled by the caller)
781
rec.Method = ImportMethodOrField(declaringType, method.Name, method.MethodSignature);
783
Writer.ByteBuffer spec = new Writer.ByteBuffer(10);
784
Signature.WriteMethodSpec(this, spec, genericParameters);
785
rec.Instantiation = this.Blobs.Add(spec);
786
token = 0x2B000000 | this.MethodSpec.FindOrAddRecord(rec);
787
importedMethodSpecs.Add(key, token);
792
internal int ImportType(Type type)
795
if (!typeTokens.TryGetValue(type, out token))
797
if (type.HasElementType || type.IsConstructedGenericType || type.__IsFunctionPointer)
799
ByteBuffer spec = new ByteBuffer(5);
800
Signature.WriteTypeSpec(this, spec, type);
801
token = 0x1B000000 | this.TypeSpec.AddRecord(this.Blobs.Add(spec));
805
TypeRefTable.Record rec = new TypeRefTable.Record();
808
rec.ResolutionScope = GetTypeToken(type.DeclaringType).Token;
810
else if (type.Module == this)
812
rec.ResolutionScope = 1;
816
rec.ResolutionScope = ImportAssemblyRef(type.Assembly);
818
rec.TypeName = this.Strings.Add(type.__Name);
819
string ns = type.__Namespace;
820
rec.TypeNameSpace = ns == null ? 0 : this.Strings.Add(ns);
821
token = 0x01000000 | this.TypeRef.AddRecord(rec);
823
typeTokens.Add(type, token);
828
private int ImportAssemblyRef(Assembly asm)
831
if (!referencedAssemblies.TryGetValue(asm, out token))
833
// We can't write the AssemblyRef record here yet, because the identity of the assembly can still change
834
// (if it's an AssemblyBuilder).
835
token = AllocPseudoToken();
836
referencedAssemblies.Add(asm, token);
841
internal void FillAssemblyRefTable()
843
foreach (KeyValuePair<Assembly, int> kv in referencedAssemblies)
845
if (IsPseudoToken(kv.Value))
847
RegisterTokenFixup(kv.Value, FindOrAddAssemblyRef(kv.Key.GetName(), false));
852
private int FindOrAddAssemblyRef(AssemblyName name, bool alwaysAdd)
854
AssemblyRefTable.Record rec = new AssemblyRefTable.Record();
855
Version ver = name.Version ?? new Version(0, 0, 0, 0);
856
rec.MajorVersion = (ushort)ver.Major;
857
rec.MinorVersion = (ushort)ver.Minor;
858
rec.BuildNumber = (ushort)ver.Build;
859
rec.RevisionNumber = (ushort)ver.Revision;
860
rec.Flags = (int)(name.Flags & ~AssemblyNameFlags.PublicKey);
861
const AssemblyNameFlags afPA_Specified = (AssemblyNameFlags)0x0080;
862
const AssemblyNameFlags afPA_Mask = (AssemblyNameFlags)0x0070;
863
if ((name.RawFlags & afPA_Specified) != 0)
865
rec.Flags |= (int)(name.RawFlags & afPA_Mask);
867
if (name.ContentType == AssemblyContentType.WindowsRuntime)
871
byte[] publicKeyOrToken = null;
872
if (usePublicKeyAssemblyReference)
874
publicKeyOrToken = name.GetPublicKey();
876
if (publicKeyOrToken == null || publicKeyOrToken.Length == 0)
878
publicKeyOrToken = name.GetPublicKeyToken() ?? Empty<byte>.Array;
882
const int PublicKey = 0x0001;
883
rec.Flags |= PublicKey;
885
rec.PublicKeyOrToken = this.Blobs.Add(ByteBuffer.Wrap(publicKeyOrToken));
886
rec.Name = this.Strings.Add(name.Name);
887
rec.Culture = name.Culture == null ? 0 : this.Strings.Add(name.Culture);
888
if (name.hash != null)
890
rec.HashValue = this.Blobs.Add(ByteBuffer.Wrap(name.hash));
896
return 0x23000000 | (alwaysAdd ? this.AssemblyRef.AddRecord(rec) : this.AssemblyRef.FindOrAddRecord(rec));
899
internal void WriteSymbolTokenMap()
901
for (int i = 0; i < resolvedTokens.Count; i++)
903
int newToken = resolvedTokens[i];
904
// The symbol API doesn't support remapping arbitrary integers, the types have to be the same,
905
// so we copy the type from the newToken, because our pseudo tokens don't have a type.
906
// (see MethodToken.SymbolToken)
907
int oldToken = (i + 1) | (newToken & ~0xFFFFFF);
908
SymbolSupport.RemapToken(symbolWriter, oldToken, newToken);
912
internal void RegisterTokenFixup(int pseudoToken, int realToken)
914
int index = -(pseudoToken + 1);
915
while (resolvedTokens.Count <= index)
917
resolvedTokens.Add(0);
919
resolvedTokens[index] = realToken;
922
internal static bool IsPseudoToken(int token)
927
internal int ResolvePseudoToken(int pseudoToken)
929
int index = -(pseudoToken + 1);
930
return resolvedTokens[index];
933
internal void ApplyUnmanagedExports(ImageFileMachine imageFileMachine)
935
if (unmanagedExports.Count != 0)
939
if (imageFileMachine == ImageFileMachine.I386)
949
List<MethodBuilder> methods = new List<MethodBuilder>();
950
for (int i = 0; i < unmanagedExports.Count; i++)
952
if (unmanagedExports[i].mb != null)
954
methods.Add(unmanagedExports[i].mb);
957
if (methods.Count != 0)
959
RelativeVirtualAddress rva = __AddVTableFixups(methods.ToArray(), type);
960
for (int i = 0; i < unmanagedExports.Count; i++)
962
if (unmanagedExports[i].mb != null)
964
UnmanagedExport exp = unmanagedExports[i];
965
exp.rva = new RelativeVirtualAddress(rva.initializedDataOffset + (uint)(methods.IndexOf(unmanagedExports[i].mb) * size));
966
unmanagedExports[i] = exp;
973
internal void FixupMethodBodyTokens()
975
int methodToken = 0x06000001;
976
int fieldToken = 0x04000001;
977
int parameterToken = 0x08000001;
978
foreach (TypeBuilder type in types)
980
type.ResolveMethodAndFieldTokens(ref methodToken, ref fieldToken, ref parameterToken);
982
foreach (int offset in tokenFixupOffsets)
984
methodBodies.Position = offset;
985
int pseudoToken = methodBodies.GetInt32AtCurrentPosition();
986
methodBodies.Write(ResolvePseudoToken(pseudoToken));
988
foreach (VTableFixups fixup in vtablefixups)
990
for (int i = 0; i < fixup.count; i++)
992
initializedData.Position = (int)fixup.initializedDataOffset + i * fixup.SlotWidth;
993
initializedData.Write(ResolvePseudoToken(initializedData.GetInt32AtCurrentPosition()));
998
private int GetHeaderLength()
1005
4 + // ImageRuntimeVersion Length
1006
StringToPaddedUTF8Length(asm.ImageRuntimeVersion) +
1011
4 + // StringToPaddedUTF8Length("#~")
1012
4 + // #Strings Offset
1013
4 + // #Strings Size
1014
12 + // StringToPaddedUTF8Length("#Strings")
1017
4 + // StringToPaddedUTF8Length("#US")
1020
8 + // StringToPaddedUTF8Length("#GUID")
1021
(Blobs.IsEmpty ? 0 :
1025
8 // StringToPaddedUTF8Length("#Blob")
1029
internal int MetadataLength
1033
return GetHeaderLength() + (Blobs.IsEmpty ? 0 : Blobs.Length) + Tables.Length + Strings.Length + UserStrings.Length + Guids.Length;
1037
internal void WriteMetadata(MetadataWriter mw)
1039
mw.Write(0x424A5342); // Signature ("BSJB")
1040
mw.Write((ushort)1); // MajorVersion
1041
mw.Write((ushort)1); // MinorVersion
1042
mw.Write(0); // Reserved
1043
byte[] version = StringToPaddedUTF8(asm.ImageRuntimeVersion);
1044
mw.Write(version.Length); // Length
1046
mw.Write((ushort)0); // Flags
1047
// #Blob is the only optional heap
1050
mw.Write((ushort)4); // Streams
1054
mw.Write((ushort)5); // Streams
1057
int offset = GetHeaderLength();
1060
mw.Write(offset); // Offset
1061
mw.Write(Tables.Length); // Size
1062
mw.Write(StringToPaddedUTF8("#~"));
1063
offset += Tables.Length;
1065
mw.Write(offset); // Offset
1066
mw.Write(Strings.Length); // Size
1067
mw.Write(StringToPaddedUTF8("#Strings"));
1068
offset += Strings.Length;
1070
mw.Write(offset); // Offset
1071
mw.Write(UserStrings.Length); // Size
1072
mw.Write(StringToPaddedUTF8("#US"));
1073
offset += UserStrings.Length;
1075
mw.Write(offset); // Offset
1076
mw.Write(Guids.Length); // Size
1077
mw.Write(StringToPaddedUTF8("#GUID"));
1078
offset += Guids.Length;
1082
mw.Write(offset); // Offset
1083
mw.Write(Blobs.Length); // Size
1084
mw.Write(StringToPaddedUTF8("#Blob"));
1089
UserStrings.Write(mw);
1097
private static int StringToPaddedUTF8Length(string str)
1099
return (System.Text.Encoding.UTF8.GetByteCount(str) + 4) & ~3;
1102
private static byte[] StringToPaddedUTF8(string str)
1104
byte[] buf = new byte[(System.Text.Encoding.UTF8.GetByteCount(str) + 4) & ~3];
1105
System.Text.Encoding.UTF8.GetBytes(str, 0, str.Length, buf, 0);
1109
internal override void ExportTypes(int fileToken, ModuleBuilder manifestModule)
1111
manifestModule.ExportTypes(types.ToArray(), fileToken);
1114
internal void ExportTypes(Type[] types, int fileToken)
1116
Dictionary<Type, int> declaringTypes = new Dictionary<Type, int>();
1117
foreach (Type type in types)
1119
if (!type.IsModulePseudoType && IsVisible(type))
1121
ExportedTypeTable.Record rec = new ExportedTypeTable.Record();
1122
rec.Flags = (int)type.Attributes;
1123
// LAMESPEC ECMA says that TypeDefId is a row index, but it should be a token
1124
rec.TypeDefId = type.MetadataToken;
1125
rec.TypeName = this.Strings.Add(type.__Name);
1126
string ns = type.__Namespace;
1127
rec.TypeNamespace = ns == null ? 0 : this.Strings.Add(ns);
1130
rec.Implementation = declaringTypes[type.DeclaringType];
1134
rec.Implementation = fileToken;
1136
int exportTypeToken = 0x27000000 | this.ExportedType.AddRecord(rec);
1137
declaringTypes.Add(type, exportTypeToken);
1142
private static bool IsVisible(Type type)
1144
// NOTE this is not the same as Type.IsVisible, because that doesn't take into account family access
1145
return type.IsPublic || ((type.IsNestedFamily || type.IsNestedFamORAssem || type.IsNestedPublic) && IsVisible(type.DeclaringType));
1148
internal void AddConstant(int parentToken, object defaultValue)
1150
ConstantTable.Record rec = new ConstantTable.Record();
1151
rec.Parent = parentToken;
1152
ByteBuffer val = new ByteBuffer(16);
1153
if (defaultValue == null)
1155
rec.Type = Signature.ELEMENT_TYPE_CLASS;
1158
else if (defaultValue is bool)
1160
rec.Type = Signature.ELEMENT_TYPE_BOOLEAN;
1161
val.Write((bool)defaultValue ? (byte)1 : (byte)0);
1163
else if (defaultValue is char)
1165
rec.Type = Signature.ELEMENT_TYPE_CHAR;
1166
val.Write((char)defaultValue);
1168
else if (defaultValue is sbyte)
1170
rec.Type = Signature.ELEMENT_TYPE_I1;
1171
val.Write((sbyte)defaultValue);
1173
else if (defaultValue is byte)
1175
rec.Type = Signature.ELEMENT_TYPE_U1;
1176
val.Write((byte)defaultValue);
1178
else if (defaultValue is short)
1180
rec.Type = Signature.ELEMENT_TYPE_I2;
1181
val.Write((short)defaultValue);
1183
else if (defaultValue is ushort)
1185
rec.Type = Signature.ELEMENT_TYPE_U2;
1186
val.Write((ushort)defaultValue);
1188
else if (defaultValue is int)
1190
rec.Type = Signature.ELEMENT_TYPE_I4;
1191
val.Write((int)defaultValue);
1193
else if (defaultValue is uint)
1195
rec.Type = Signature.ELEMENT_TYPE_U4;
1196
val.Write((uint)defaultValue);
1198
else if (defaultValue is long)
1200
rec.Type = Signature.ELEMENT_TYPE_I8;
1201
val.Write((long)defaultValue);
1203
else if (defaultValue is ulong)
1205
rec.Type = Signature.ELEMENT_TYPE_U8;
1206
val.Write((ulong)defaultValue);
1208
else if (defaultValue is float)
1210
rec.Type = Signature.ELEMENT_TYPE_R4;
1211
val.Write((float)defaultValue);
1213
else if (defaultValue is double)
1215
rec.Type = Signature.ELEMENT_TYPE_R8;
1216
val.Write((double)defaultValue);
1218
else if (defaultValue is string)
1220
rec.Type = Signature.ELEMENT_TYPE_STRING;
1221
foreach (char c in (string)defaultValue)
1226
else if (defaultValue is DateTime)
1228
rec.Type = Signature.ELEMENT_TYPE_I8;
1229
val.Write(((DateTime)defaultValue).Ticks);
1233
throw new ArgumentException();
1235
rec.Value = this.Blobs.Add(val);
1236
this.Constant.AddRecord(rec);
1239
ModuleBuilder ITypeOwner.ModuleBuilder
1241
get { return this; }
1244
internal override Type ResolveType(int metadataToken, IGenericContext context)
1246
if (metadataToken >> 24 != TypeDefTable.Index)
1248
throw new NotImplementedException();
1250
return types[(metadataToken & 0xFFFFFF) - 1];
1253
public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1255
if (genericTypeArguments != null || genericMethodArguments != null)
1257
throw new NotImplementedException();
1259
// this method is inefficient, but since it isn't used we don't care
1260
if ((metadataToken >> 24) == MemberRefTable.Index)
1262
foreach (KeyValuePair<MemberRefKey, int> kv in importedMemberRefs)
1264
if (kv.Value == metadataToken)
1266
return kv.Key.LookupMethod();
1270
// HACK if we're given a SymbolToken, we need to convert back
1271
if ((metadataToken & 0xFF000000) == 0x06000000)
1273
metadataToken = -(metadataToken & 0x00FFFFFF);
1275
foreach (Type type in types)
1277
MethodBase method = ((TypeBuilder)type).LookupMethod(metadataToken);
1283
return ((TypeBuilder)moduleType).LookupMethod(metadataToken);
1286
public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1288
throw new NotImplementedException();
1291
public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1293
throw new NotImplementedException();
1296
public override string ResolveString(int metadataToken)
1298
throw new NotImplementedException();
1301
public override string FullyQualifiedName
1303
get { return Path.GetFullPath(Path.Combine(asm.dir, fileName)); }
1306
public override string Name
1308
get { return fileName; }
1311
public override Guid ModuleVersionId
1313
get { return mvid; }
1316
public void __SetModuleVersionId(Guid guid)
1321
public override Type[] __ResolveOptionalParameterTypes(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments, out CustomModifiers[] customModifiers)
1323
throw new NotImplementedException();
1326
public override string ScopeName
1328
get { return moduleName; }
1331
public ISymbolWriter GetSymWriter()
1333
return symbolWriter;
1336
public void DefineUnmanagedResource(string resourceFileName)
1338
// This method reads the specified resource file (Win32 .res file) and converts it into the appropriate format and embeds it in the .rsrc section,
1339
// also setting the Resource Directory entry.
1340
unmanagedResources = new ResourceSection();
1341
unmanagedResources.ExtractResources(System.IO.File.ReadAllBytes(resourceFileName));
1344
public bool IsTransient()
1349
public void SetUserEntryPoint(MethodInfo entryPoint)
1351
int token = entryPoint.MetadataToken;
1354
token = -token | 0x06000000;
1356
if (symbolWriter != null)
1358
symbolWriter.SetUserEntryPoint(new SymbolToken(token));
1362
public StringToken GetStringConstant(string str)
1364
return new StringToken(this.UserStrings.Add(str) | (0x70 << 24));
1367
public SignatureToken GetSignatureToken(SignatureHelper sigHelper)
1369
return new SignatureToken(this.StandAloneSig.FindOrAddRecord(this.Blobs.Add(sigHelper.GetSignature(this))) | (StandAloneSigTable.Index << 24));
1372
public SignatureToken GetSignatureToken(byte[] sigBytes, int sigLength)
1374
return new SignatureToken(this.StandAloneSig.FindOrAddRecord(this.Blobs.Add(ByteBuffer.Wrap(sigBytes, sigLength))) | (StandAloneSigTable.Index << 24));
1377
public MethodInfo GetArrayMethod(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
1379
return new ArrayMethod(this, arrayClass, methodName, callingConvention, returnType, parameterTypes);
1382
public MethodToken GetArrayMethodToken(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
1384
return GetMethodToken(GetArrayMethod(arrayClass, methodName, callingConvention, returnType, parameterTypes));
1387
internal override Type GetModuleType()
1392
internal override IKVM.Reflection.Reader.ByteReader GetBlob(int blobIndex)
1394
return Blobs.GetBlob(blobIndex);
1397
internal int GetSignatureBlobIndex(Signature sig)
1399
ByteBuffer bb = new ByteBuffer(16);
1400
sig.WriteSig(this, bb);
1401
return this.Blobs.Add(bb);
1405
public new long __ImageBase
1407
get { return imageBaseAddress; }
1408
set { imageBaseAddress = value; }
1411
protected override long GetImageBaseImpl()
1413
return imageBaseAddress;
1416
public new long __StackReserve
1418
get { return stackReserve; }
1419
set { stackReserve = value; }
1422
protected override long GetStackReserveImpl()
1424
return stackReserve;
1427
[Obsolete("Use __StackReserve property.")]
1428
public void __SetStackReserve(long stackReserve)
1430
__StackReserve = stackReserve;
1433
internal ulong GetStackReserve(ulong defaultValue)
1435
return stackReserve == -1 ? defaultValue : (ulong)stackReserve;
1438
public new int __FileAlignment
1440
get { return fileAlignment; }
1441
set { fileAlignment = value; }
1444
protected override int GetFileAlignmentImpl()
1446
return fileAlignment;
1449
public new DllCharacteristics __DllCharacteristics
1451
get { return dllCharacteristics; }
1452
set { dllCharacteristics = value; }
1455
protected override DllCharacteristics GetDllCharacteristicsImpl()
1457
return dllCharacteristics;
1460
public override int MDStreamVersion
1462
get { return asm.mdStreamVersion; }
1465
private int AddTypeRefByName(int resolutionScope, string ns, string name)
1467
TypeRefTable.Record rec = new TypeRefTable.Record();
1468
rec.ResolutionScope = resolutionScope;
1469
rec.TypeName = this.Strings.Add(name);
1470
rec.TypeNameSpace = ns == null ? 0 : this.Strings.Add(ns);
1471
return 0x01000000 | this.TypeRef.AddRecord(rec);
1474
public void __Save(PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1476
SaveImpl(null, portableExecutableKind, imageFileMachine);
1479
public void __Save(Stream stream, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1481
if (!stream.CanRead || !stream.CanWrite || !stream.CanSeek || stream.Position != 0)
1483
throw new ArgumentException("Stream must support read/write/seek and current position must be zero.", "stream");
1485
SaveImpl(stream, portableExecutableKind, imageFileMachine);
1488
private void SaveImpl(Stream streamOrNull, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1491
PopulatePropertyAndEventTables();
1492
IList<CustomAttributeData> attributes = asm.GetCustomAttributesData(null);
1493
if (attributes.Count > 0)
1495
int mscorlib = ImportAssemblyRef(universe.Mscorlib);
1496
int[] placeholderTokens = new int[4];
1497
string[] placeholderTypeNames = new string[] { "AssemblyAttributesGoHere", "AssemblyAttributesGoHereM", "AssemblyAttributesGoHereS", "AssemblyAttributesGoHereSM" };
1498
foreach (CustomAttributeData cad in attributes)
1501
if (cad.Constructor.DeclaringType.BaseType == universe.System_Security_Permissions_CodeAccessSecurityAttribute)
1503
if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute)
1512
else if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute)
1520
if (placeholderTokens[index] == 0)
1522
// we manually add a TypeRef without looking it up in mscorlib, because Mono and Silverlight's mscorlib don't have these types
1523
placeholderTokens[index] = AddTypeRefByName(mscorlib, "System.Runtime.CompilerServices", placeholderTypeNames[index]);
1525
SetCustomAttribute(placeholderTokens[index], cad.__ToBuilder());
1528
FillAssemblyRefTable();
1530
ModuleWriter.WriteModule(null, null, this, PEFileKinds.Dll, portableExecutableKind, imageFileMachine, unmanagedResources, 0, streamOrNull);
1533
public void __AddAssemblyReference(AssemblyName assemblyName)
1535
__AddAssemblyReference(assemblyName, null);
1538
public void __AddAssemblyReference(AssemblyName assemblyName, Assembly assembly)
1540
if (referencedAssemblyNames == null)
1542
referencedAssemblyNames = new List<AssemblyName>();
1544
referencedAssemblyNames.Add((AssemblyName)assemblyName.Clone());
1545
int token = FindOrAddAssemblyRef(assemblyName, true);
1546
if (assembly != null)
1548
referencedAssemblies.Add(assembly, token);
1552
public override AssemblyName[] __GetReferencedAssemblies()
1554
List<AssemblyName> list = new List<AssemblyName>();
1555
if (referencedAssemblyNames != null)
1557
foreach (AssemblyName name in referencedAssemblyNames)
1559
if (!list.Contains(name))
1565
foreach (Assembly asm in referencedAssemblies.Keys)
1567
AssemblyName name = asm.GetName();
1568
if (!list.Contains(name))
1573
return list.ToArray();
1576
public void __AddModuleReference(string module)
1578
this.ModuleRef.FindOrAddRecord(module == null ? 0 : this.Strings.Add(module));
1581
public override string[] __GetReferencedModules()
1583
string[] arr = new string[this.ModuleRef.RowCount];
1584
for (int i = 0; i < arr.Length; i++)
1586
arr[i] = this.Strings.Find(this.ModuleRef.records[i]);
1591
public override Type[] __GetReferencedTypes()
1593
List<Type> list = new List<Type>();
1594
foreach (KeyValuePair<Type, int> kv in typeTokens)
1596
if (kv.Value >> 24 == TypeRefTable.Index)
1601
return list.ToArray();
1604
public override Type[] __GetExportedTypes()
1606
throw new NotImplementedException();
1609
public int __AddModule(int flags, string name, byte[] hash)
1611
FileTable.Record file = new FileTable.Record();
1613
file.Name = this.Strings.Add(name);
1614
file.HashValue = this.Blobs.Add(ByteBuffer.Wrap(hash));
1615
return 0x26000000 + this.File.AddRecord(file);
1618
public int __AddManifestResource(int offset, ResourceAttributes flags, string name, int implementation)
1620
ManifestResourceTable.Record res = new ManifestResourceTable.Record();
1621
res.Offset = offset;
1622
res.Flags = (int)flags;
1623
res.Name = this.Strings.Add(name);
1624
res.Implementation = implementation;
1625
return 0x28000000 + this.ManifestResource.AddRecord(res);
1628
public void __SetCustomAttributeFor(int token, CustomAttributeBuilder customBuilder)
1630
SetCustomAttribute(token, customBuilder);
1633
public RelativeVirtualAddress __AddVTableFixups(MethodBuilder[] methods, int type)
1635
initializedData.Align(8);
1636
VTableFixups fixups;
1637
fixups.initializedDataOffset = (uint)initializedData.Position;
1638
fixups.count = (ushort)methods.Length;
1639
fixups.type = (ushort)type;
1640
foreach (MethodBuilder mb in methods)
1642
initializedData.Write(mb.MetadataToken);
1643
if (fixups.SlotWidth == 8)
1645
initializedData.Write(0);
1648
vtablefixups.Add(fixups);
1649
return new RelativeVirtualAddress(fixups.initializedDataOffset);
1652
public void __AddUnmanagedExportStub(string name, int ordinal, RelativeVirtualAddress rva)
1654
AddUnmanagedExport(name, ordinal, null, rva);
1657
internal void AddUnmanagedExport(string name, int ordinal, MethodBuilder methodBuilder, RelativeVirtualAddress rva)
1659
UnmanagedExport export;
1661
export.ordinal = ordinal;
1662
export.mb = methodBuilder;
1664
unmanagedExports.Add(export);
1667
internal void SetInterfaceImplementationCustomAttribute(TypeBuilder typeBuilder, Type interfaceType, CustomAttributeBuilder cab)
1669
// NOTE since interfaceimpls are extremely common and custom attributes on them are extremely rare,
1670
// we store (and resolve) the custom attributes in such away as to avoid impacting the common case performance
1671
if (interfaceImplCustomAttributes == null)
1673
interfaceImplCustomAttributes = new List<InterfaceImplCustomAttribute>();
1675
InterfaceImplCustomAttribute rec;
1676
rec.type = typeBuilder.MetadataToken;
1677
int token = GetTypeToken(interfaceType).Token;
1678
switch (token >> 24)
1680
case TypeDefTable.Index:
1681
token = (token & 0xFFFFFF) << 2 | 0;
1683
case TypeRefTable.Index:
1684
token = (token & 0xFFFFFF) << 2 | 1;
1686
case TypeSpecTable.Index:
1687
token = (token & 0xFFFFFF) << 2 | 2;
1690
throw new InvalidOperationException();
1692
rec.interfaceType = token;
1693
rec.pseudoToken = AllocPseudoToken();
1694
interfaceImplCustomAttributes.Add(rec);
1695
SetCustomAttribute(rec.pseudoToken, cab);
1698
internal void ResolveInterfaceImplPseudoTokens()
1700
if (interfaceImplCustomAttributes != null)
1702
foreach (InterfaceImplCustomAttribute rec in interfaceImplCustomAttributes)
1704
for (int i = 0; i < InterfaceImpl.records.Length; i++)
1706
if (InterfaceImpl.records[i].Class == rec.type && InterfaceImpl.records[i].Interface == rec.interfaceType)
1708
RegisterTokenFixup(rec.pseudoToken, (InterfaceImplTable.Index << 24) | (i + 1));
1716
internal void FixupPseudoToken(ref int token)
1718
if (IsPseudoToken(token))
1720
token = ResolvePseudoToken(token);
1724
internal void SetIsSaved()
1728
throw new InvalidOperationException();
1733
internal bool IsSaved
1735
get { return saved; }
1738
internal override string GetString(int index)
1740
return this.Strings.Find(index);
1744
struct UnmanagedExport
1746
internal string name;
1747
internal int ordinal;
1748
internal RelativeVirtualAddress rva;
1749
internal MethodBuilder mb;
1752
public struct RelativeVirtualAddress
1754
internal readonly uint initializedDataOffset;
1756
internal RelativeVirtualAddress(uint initializedDataOffset)
1758
this.initializedDataOffset = initializedDataOffset;
1761
public static RelativeVirtualAddress operator +(RelativeVirtualAddress rva, int offset)
1763
return new RelativeVirtualAddress(rva.initializedDataOffset + (uint)offset);
1767
class ArrayMethod : MethodInfo
1769
private readonly Module module;
1770
private readonly Type arrayClass;
1771
private readonly string methodName;
1772
private readonly CallingConventions callingConvention;
1773
private readonly Type returnType;
1774
protected readonly Type[] parameterTypes;
1775
private MethodSignature methodSignature;
1777
internal ArrayMethod(Module module, Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
1779
this.module = module;
1780
this.arrayClass = arrayClass;
1781
this.methodName = methodName;
1782
this.callingConvention = callingConvention;
1783
this.returnType = returnType ?? module.universe.System_Void;
1784
this.parameterTypes = Util.Copy(parameterTypes);
1787
public override MethodBody GetMethodBody()
1789
throw new InvalidOperationException();
1792
public override int __MethodRVA
1794
get { throw new InvalidOperationException(); }
1797
public override MethodImplAttributes GetMethodImplementationFlags()
1799
throw new NotSupportedException();
1802
public override ParameterInfo[] GetParameters()
1804
throw new NotSupportedException();
1807
internal override int ImportTo(ModuleBuilder module)
1809
return module.ImportMethodOrField(arrayClass, methodName, MethodSignature);
1812
public override MethodAttributes Attributes
1814
get { throw new NotSupportedException(); }
1817
public override CallingConventions CallingConvention
1819
get { return callingConvention; }
1822
public override Type DeclaringType
1824
get { return arrayClass; }
1827
internal override MethodSignature MethodSignature
1831
if (methodSignature == null)
1833
methodSignature = MethodSignature.MakeFromBuilder(returnType, parameterTypes, new PackedCustomModifiers(), callingConvention, 0);
1835
return methodSignature;
1839
public override Module Module
1841
// FXBUG like .NET, we return the module that GetArrayMethod was called on, not the module associated with the array type
1842
get { return module; }
1845
public override string Name
1847
get { return methodName; }
1850
internal override int ParameterCount
1852
get { return parameterTypes.Length; }
1855
public override ParameterInfo ReturnParameter
1857
// FXBUG like .NET, we throw NotImplementedException
1858
get { throw new NotImplementedException(); }
1861
public override Type ReturnType
1863
get { return returnType; }
1866
internal override bool HasThis
1868
get { return (callingConvention & (CallingConventions.HasThis | CallingConventions.ExplicitThis)) == CallingConventions.HasThis; }
1871
internal override int GetCurrentToken()
1873
return this.MetadataToken;
1876
internal override bool IsBaked
1878
get { return arrayClass.IsBaked; }