25using System.Collections.Generic;
26using System.Diagnostics;
27using System.Diagnostics.SymbolStore;
29using System.Reflection.Metadata;
30using System.Reflection.Metadata.Ecma335;
31using System.Resources;
32using System.Runtime.InteropServices;
45 struct ResourceWriterRecord
49 readonly ResourceWriter rw;
50 readonly Stream stream;
51 readonly ResourceAttributes attributes;
59 internal ResourceWriterRecord(
string name, Stream stream, ResourceAttributes attributes) :
60 this(name, null, stream, attributes)
72 internal ResourceWriterRecord(
string name, ResourceWriter rw, Stream stream, ResourceAttributes attributes)
77 this.attributes = attributes;
80 internal readonly
int GetLength() => 4 + (int)stream.Length;
86 internal readonly
void Write(ModuleBuilder module)
92 module.resourceStream.Align(8);
93 var offset = module.resourceStream.Count;
96 module.resourceStream.WriteInt32((
int)stream.Length);
98 var buffer =
new byte[8192];
100 while ((length = stream.Read(buffer, 0, buffer.Length)) != 0)
101 module.resourceStream.WriteBytes(buffer, 0, length);
106 rec.Flags = (int)attributes;
107 rec.Name = module.GetOrAddString(name);
108 rec.Implementation = 0;
109 module.ManifestResourceTable.AddRecord(rec);
112 internal readonly
void Close()
119 internal struct VTableFixups
122 internal uint initializedDataOffset;
123 internal ushort count;
124 internal ushort type;
126 internal readonly
int SlotWidth => (type & 0x02) == 0 ? 4 : 8;
130 struct InterfaceImplCustomAttribute
134 internal int interfaceType;
135 internal int pseudoToken;
139 readonly
struct MemberRefKey : IEquatable<MemberRefKey>
143 readonly
string name;
152 internal MemberRefKey(
Type type,
string name,
Signature signature)
156 this.signature = signature;
159 public bool Equals(MemberRefKey other) => other.type.Equals(type) && other.name == name && other.signature.Equals(signature);
161 public override bool Equals(
object obj) => obj is MemberRefKey other && Equals(other);
163 public override int GetHashCode()
165 return type.GetHashCode() + name.GetHashCode() + signature.GetHashCode();
175 readonly
struct MethodSpecKey : IEquatable<MethodSpecKey>
179 readonly
string name;
181 readonly
Type[] genericParameters;
194 this.signature = signature;
195 this.genericParameters = genericParameters;
198 public bool Equals(MethodSpecKey other)
200 return other.type.Equals(type) && other.name == name && other.signature.Equals(signature) &&
Util.ArrayEquals(other.genericParameters, genericParameters);
203 public override bool Equals(
object obj) => obj is MethodSpecKey other && Equals(other);
205 public override int GetHashCode() => type.GetHashCode() + name.GetHashCode() + signature.GetHashCode() +
Util.GetHashCode(genericParameters);
209 static readonly
bool usePublicKeyAssemblyReference =
false;
211 readonly MetadataBuilder metadata;
212 readonly BlobBuilder ilStream;
213 readonly MethodBodyStreamEncoder methodBodyEncoder;
214 readonly BlobBuilder resourceStream;
215 readonly AssemblyBuilder
asm;
217 ReservedBlob<GuidHandle> mvidFixup;
219 ulong imageBaseAddress = 0;
220 uint fileAlignment = 0;
221 ulong stackReserve = 0;
222 DllCharacteristics dllCharacteristics = DllCharacteristics.DynamicBase | DllCharacteristics.NoSEH | DllCharacteristics.NXCompat | DllCharacteristics.TerminalServerAware;
223 internal readonly
string moduleName;
224 internal readonly
string fileName;
225 readonly TypeBuilder moduleType;
226 readonly List<TypeBuilder> types =
new List<TypeBuilder>();
227 readonly Dictionary<Type, int> typeTokens =
new Dictionary<Type, int>();
228 readonly Dictionary<Type, int> memberRefTypeTokens =
new Dictionary<Type, int>();
229 internal readonly List<int> tokenFixupOffsets =
new List<int>();
230 internal readonly BlobBuilder initializedDataStream =
new BlobBuilder(512);
232 readonly Dictionary<MemberRefKey, int> importedMemberRefs =
new Dictionary<MemberRefKey, int>();
233 readonly Dictionary<MethodSpecKey, int> importedMethodSpecs =
new Dictionary<MethodSpecKey, int>();
234 readonly Dictionary<Assembly, int> referencedAssemblies =
new Dictionary<Assembly, int>();
235 List<AssemblyName> referencedAssemblyNames;
236 int nextPseudoToken = -1;
237 readonly List<int> resolvedTokens =
new List<int>();
238 ISymbolWriter symbolWriter;
240 internal readonly Dictionary<StringHandle, string> strings =
new();
241 internal readonly Dictionary<BlobHandle, BlobBuilder> blobs =
new();
242 List<InterfaceImplCustomAttribute> interfaceImplCustomAttributes;
243 readonly List<ResourceWriterRecord> resourceWriters =
new List<ResourceWriterRecord>();
253 internal ModuleBuilder(AssemblyBuilder
asm,
string moduleName,
string fileName) :
256 this.metadata =
new MetadataBuilder();
257 this.ilStream =
new BlobBuilder();
258 this.methodBodyEncoder =
new MethodBodyStreamEncoder(ilStream);
259 this.resourceStream =
new BlobBuilder();
261 this.asm =
asm ??
throw new ArgumentNullException(nameof(
asm));
262 this.metadata = metadata ??
throw new ArgumentNullException(nameof(metadata));
263 this.moduleName = moduleName;
264 this.fileName = fileName;
266 if (Universe.Deterministic ==
false)
268 __PEHeaderTimeDateStamp = DateTime.UtcNow;
269 mvid = Guid.NewGuid();
273 mvidFixup = metadata.ReserveGuid();
274 ModuleTable.Add(0, GetOrAddString(moduleName), mvidFixup.Handle,
default,
default);
277 moduleType =
new TypeBuilder(
this,
null,
"<Module>");
278 types.Add(moduleType);
284 internal MetadataBuilder Metadata => metadata;
289 internal BlobBuilder ILStream => ilStream;
294 internal MethodBodyStreamEncoder MethodBodyEncoder => methodBodyEncoder;
299 internal BlobBuilder InitializedDataStream => initializedDataStream;
304 internal BlobBuilder ResourceStream => resourceStream;
311 internal StringHandle GetOrAddString(
string value)
313 var h = metadata.GetOrAddString(value);
323 internal override string GetString(StringHandle handle) => strings.TryGetValue(handle, out var value) ? value :
throw new InvalidOperationException();
330 internal BlobHandle GetOrAddBlob(BlobBuilder value)
332 var h = metadata.GetOrAddBlob(value);
342 internal BlobHandle GetOrAddBlob(
byte[] value)
344 var b =
new BlobBuilder();
346 return GetOrAddBlob(b);
354 internal BlobHandle GetOrAddBlobUTF8(
string value)
356 return metadata.GetOrAddBlobUTF8(value);
364 internal BlobBuilder GetBlob(BlobHandle handle) => blobs.TryGetValue(handle, out var value) ? value :
throw new InvalidOperationException();
371 internal override ByteReader GetBlobReader(BlobHandle handle)
373 var b = GetBlob(handle).ToArray();
381 internal void SetSymWriter(ISymbolWriter writer)
383 this.symbolWriter = writer;
386 internal void PopulatePropertyAndEventTables()
391 foreach (var type
in types)
392 type.PopulatePropertyAndEventTables();
395 internal void WriteTypeDefTable()
399 foreach (var type
in types)
400 type.WriteTypeDefRecord(
ref fieldList,
ref methodList);
403 internal void WriteMethodDefTable()
406 foreach (var type
in types)
407 type.WriteMethodDefRecords(
ref paramList);
410 internal void WriteParamTable()
412 foreach (var type
in types)
413 type.WriteParamRecords();
416 internal void WriteFieldTable()
418 foreach (var type
in types)
419 type.WriteFieldRecords();
422 internal int AllocPseudoToken()
424 return nextPseudoToken--;
427 public TypeBuilder DefineType(
string name)
429 return DefineType(name, TypeAttributes.Class);
432 public TypeBuilder DefineType(
string name, TypeAttributes attr)
434 return DefineType(name, attr,
null);
437 public TypeBuilder DefineType(
string name, TypeAttributes attr,
Type parent)
439 return DefineType(name, attr, parent, PackingSize.Unspecified, 0);
442 public TypeBuilder DefineType(
string name, TypeAttributes attr,
Type parent,
int typesize)
444 return DefineType(name, attr, parent, PackingSize.Unspecified, typesize);
447 public TypeBuilder DefineType(
string name, TypeAttributes attr,
Type parent, PackingSize packsize)
449 return DefineType(name, attr, parent, packsize, 0);
452 public TypeBuilder DefineType(
string name, TypeAttributes attr,
Type parent,
Type[] interfaces)
454 var tb = DefineType(name, attr, parent);
455 foreach (
Type iface
in interfaces)
456 tb.AddInterfaceImplementation(iface);
461 public TypeBuilder DefineType(
string name, TypeAttributes attr,
Type parent, PackingSize packingSize,
int typesize)
464 int lastdot = name.LastIndexOf(
'.');
467 ns = name.Substring(0, lastdot);
468 name = name.Substring(lastdot + 1);
471 var typeBuilder = __DefineType(ns, name);
472 typeBuilder.__SetAttributes(attr);
473 typeBuilder.SetParent(parent);
474 if (packingSize != PackingSize.Unspecified || typesize != 0)
475 typeBuilder.__SetLayout((
int)packingSize, typesize);
480 public TypeBuilder __DefineType(
string ns,
string name)
482 return DefineType(
this, ns, name);
485 internal TypeBuilder DefineType(
ITypeOwner owner,
string ns,
string name)
487 var typeBuilder =
new TypeBuilder(owner, ns, name);
488 types.Add(typeBuilder);
492 public EnumBuilder DefineEnum(
string name, TypeAttributes visibility,
Type underlyingType)
494 var tb = DefineType(name, (visibility & TypeAttributes.VisibilityMask) | TypeAttributes.Sealed, Universe.System_Enum);
495 var fb = tb.DefineField(
"value__", underlyingType, FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
496 return new EnumBuilder(tb, fb);
499 public FieldBuilder __DefineField(
string name,
Type type, CustomModifiers customModifiers, FieldAttributes attributes)
501 return moduleType.__DefineField(name, type, customModifiers, attributes);
504 [Obsolete(
"Please use __DefineField(string, Type, CustomModifiers, FieldAttributes) instead.")]
505 public FieldBuilder __DefineField(
string name,
Type type,
Type[] requiredCustomModifiers,
Type[] optionalCustomModifiers, FieldAttributes attributes)
507 return moduleType.DefineField(name, type, requiredCustomModifiers, optionalCustomModifiers, attributes);
510 public ConstructorBuilder __DefineModuleInitializer(MethodAttributes visibility)
512 return moduleType.DefineConstructor(visibility | MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard,
Type.EmptyTypes);
515 public FieldBuilder DefineUninitializedData(
string name,
int size, FieldAttributes attributes)
517 return moduleType.DefineUninitializedData(name, size, attributes);
520 public FieldBuilder DefineInitializedData(
string name,
byte[] data, FieldAttributes attributes)
522 return moduleType.DefineInitializedData(name, data, attributes);
525 public MethodBuilder DefineGlobalMethod(
string name, MethodAttributes attributes,
Type returnType,
Type[] parameterTypes)
527 return moduleType.DefineMethod(name, attributes, returnType, parameterTypes);
530 public MethodBuilder DefineGlobalMethod(
string name, MethodAttributes attributes, CallingConventions callingConvention,
Type returnType,
Type[] parameterTypes)
532 return moduleType.DefineMethod(name, attributes, callingConvention, returnType, parameterTypes);
535 public MethodBuilder DefineGlobalMethod(
string name, MethodAttributes attributes, CallingConventions callingConvention,
Type returnType,
Type[] requiredReturnTypeCustomModifiers,
Type[] optionalReturnTypeCustomModifiers,
Type[] parameterTypes,
Type[][] requiredParameterTypeCustomModifiers,
Type[][] optionalParameterTypeCustomModifiers)
537 return moduleType.DefineMethod(name, attributes, callingConvention, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
540 public MethodBuilder DefinePInvokeMethod(
string name,
string dllName, MethodAttributes attributes, CallingConventions callingConvention,
Type returnType,
Type[] parameterTypes,
CallingConvention nativeCallConv, CharSet nativeCharSet)
542 return moduleType.DefinePInvokeMethod(name, dllName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
545 public MethodBuilder DefinePInvokeMethod(
string name,
string dllName,
string entryName, MethodAttributes attributes, CallingConventions callingConvention,
Type returnType,
Type[] parameterTypes,
CallingConvention nativeCallConv, CharSet nativeCharSet)
547 return moduleType.DefinePInvokeMethod(name, dllName, entryName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
550 public void CreateGlobalFunctions()
552 moduleType.CreateType();
555 internal void AddTypeForwarder(
Type type,
bool includeNested)
559 if (includeNested && !type.__IsMissing)
561 foreach (var nested
in type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic))
565 AddTypeForwarder(nested,
true);
570 int ExportType(
Type type)
573 if (
asm.ImageRuntimeVersion ==
"v2.0.50727")
576 rec.TypeDefId = type.MetadataToken;
579 SetTypeNameAndTypeNamespace(type.TypeName, out rec.TypeName, out rec.TypeNamespace);
583 rec.Implementation = ExportType(type.DeclaringType);
587 rec.Flags = 0x00200000;
588 rec.Implementation = ImportAssemblyRef(type.Assembly);
594 void SetTypeNameAndTypeNamespace(
TypeName name, out StringHandle typeName, out StringHandle typeNamespace)
596 typeName = GetOrAddString(name.Name);
597 typeNamespace = name.Namespace ==
null ? default : GetOrAddString(name.Namespace);
600 public void SetCustomAttribute(
ConstructorInfo con,
byte[] binaryAttribute)
602 SetCustomAttribute(
new CustomAttributeBuilder(con, binaryAttribute));
605 public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
607 SetCustomAttribute(0x00000001, customBuilder);
610 internal void SetCustomAttribute(
int token, CustomAttributeBuilder customBuilder)
614 rec.Constructor = asm.IsWindowsRuntime ? customBuilder.Constructor.ImportTo(
this) : GetConstructorToken(customBuilder.Constructor).Token;
615 rec.Value = customBuilder.WriteBlob(
this);
619 void AddDeclSecurityRecord(
int token,
int action, BlobHandle blob)
622 rec.Action = (short)action;
624 rec.PermissionSet = blob;
628 internal void AddDeclarativeSecurity(
int token,
System.Security.Permissions.SecurityAction securityAction,
System.Security.PermissionSet permissionSet)
630 AddDeclSecurityRecord(token, (
int)securityAction, GetOrAddBlob(
System.
Text.Encoding.Unicode.GetBytes(permissionSet.ToXml().ToString())));
633 internal void AddDeclarativeSecurity(
int token, List<CustomAttributeBuilder> declarativeSecurity)
635 var ordered =
new Dictionary<int, List<CustomAttributeBuilder>>();
636 foreach (var cab
in declarativeSecurity)
640 if (cab.ConstructorArgumentCount == 0)
642 action = (int)
System.Security.Permissions.SecurityAction.LinkDemand;
646 action = (int)cab.GetConstructorArgument(0);
649 if (cab.IsLegacyDeclSecurity)
651 AddDeclSecurityRecord(token, action, cab.WriteLegacyDeclSecurityBlob(
this));
655 if (!ordered.TryGetValue(action, out var list))
657 list =
new List<CustomAttributeBuilder>();
658 ordered.Add(action, list);
664 foreach (KeyValuePair<
int, List<CustomAttributeBuilder>> kv
in ordered)
665 AddDeclSecurityRecord(token, kv.Key, WriteDeclSecurityBlob(kv.Value));
668 BlobHandle WriteDeclSecurityBlob(List<CustomAttributeBuilder> list)
673 bb.WriteCompressedUInt(list.Count);
674 foreach (var cab
in list)
676 bb.Write(cab.Constructor.DeclaringType.AssemblyQualifiedName);
678 cab.WriteNamedArgumentsForDeclSecurity(
this, namedArgs);
679 bb.WriteCompressedUInt(namedArgs.Length);
683 return GetOrAddBlob(bb.ToArray());
686 public void DefineManifestResource(
string name, Stream stream, ResourceAttributes attribute)
688 resourceWriters.Add(
new ResourceWriterRecord(name, stream, attribute));
691 public IResourceWriter DefineResource(
string name,
string description)
693 return DefineResource(name, description, ResourceAttributes.Public);
696 public IResourceWriter DefineResource(
string name,
string description, ResourceAttributes attribute)
699 var mem =
new MemoryStream();
700 var rw =
new ResourceWriter(mem);
701 resourceWriters.Add(
new ResourceWriterRecord(name, rw, mem, attribute));
709 internal void WriteResources()
711 foreach (var rwr
in resourceWriters)
725 foreach (var type
in types)
726 if (type.TypeName == name)
732 internal override Type FindTypeIgnoreCase(
TypeName lowerCaseName)
734 foreach (var type
in types)
735 if (type.TypeName.ToLowerInvariant() == lowerCaseName)
741 internal override void GetTypesImpl(List<Type> list)
743 foreach (var type
in types)
744 if (type != moduleType)
748 public ISymbolDocumentWriter DefineDocument(
string url, Guid language, Guid languageVendor, Guid documentType)
750 if (symbolWriter !=
null)
751 return symbolWriter.DefineDocument(url, language, languageVendor, documentType);
753 throw new NotSupportedException();
762 public void SetUserEntryPoint(
MethodInfo entryPoint)
768 if (entryPoint ==
null)
769 throw new ArgumentNullException(
"entryPoint");
772 if (symbolWriter ==
null)
773 throw new InvalidOperationException(
"Not a debug ModuleBuilder.");
775 if (entryPoint.DeclaringType !=
null)
777 if (!entryPoint.Module.Equals(
this))
780 throw new InvalidOperationException(
"The argument passed in was not from the same ModuleBuilder.");
788 MethodBuilder mb = entryPoint as MethodBuilder;
789 if (mb !=
null && mb.ModuleBuilder !=
this)
792 throw new InvalidOperationException(
"The argument passed in was not from the same ModuleBuilder.");
797 SymbolToken tkMethod =
new SymbolToken(GetMethodToken(entryPoint).Token);
800 symbolWriter.SetUserEntryPoint(tkMethod);
803 public int __GetAssemblyToken(
Assembly assembly)
805 return ImportAssemblyRef(assembly);
808 public TypeToken GetTypeToken(
string name)
810 return new TypeToken(GetType(name,
true,
false).MetadataToken);
813 public TypeToken GetTypeToken(
Type type)
815 if (type.Module ==
this && !
asm.IsWindowsRuntime)
816 return new TypeToken(type.GetModuleBuilderToken());
818 return new TypeToken(ImportType(type));
821 internal int GetTypeTokenForMemberRef(
Type type)
823 if (type.__IsMissing)
825 return ImportType(type);
827 else if (type.IsGenericTypeDefinition)
829 if (memberRefTypeTokens.TryGetValue(type, out var token) ==
false)
832 Signature.WriteTypeSpec(
this, spec, type);
833 token = MetadataTokens.GetToken(MetadataTokens.TypeSpecificationHandle(
TypeSpecTable.AddRecord(GetOrAddBlob(spec.ToArray()))));
834 memberRefTypeTokens.Add(type, token);
838 else if (type.IsModulePseudoType)
840 return MetadataTokens.GetToken(MetadataTokens.ModuleReferenceHandle(
ModuleRefTable.FindOrAddRecord(GetOrAddString(type.Module.ScopeName))));
844 return GetTypeToken(type).Token;
848 static bool IsFromGenericTypeDefinition(
MemberInfo member)
850 var decl = member.DeclaringType;
851 return decl !=
null && !decl.__IsMissing && decl.IsGenericTypeDefinition;
854 public FieldToken GetFieldToken(
FieldInfo field)
859 var fb = field as FieldBuilder;
860 if (fb !=
null && fb.Module ==
this && !IsFromGenericTypeDefinition(fb))
862 return new FieldToken(fb.MetadataToken);
866 return new FieldToken(field.ImportTo(
this));
870 public MethodToken GetMethodToken(
MethodInfo method)
872 var mb = method as MethodBuilder;
873 if (mb !=
null && mb.ModuleBuilder ==
this)
874 return new MethodToken(mb.MetadataToken);
876 return new MethodToken(method.ImportTo(
this));
879 public MethodToken GetMethodToken(
MethodInfo method, IEnumerable<Type> optionalParameterTypes)
881 return __GetMethodToken(method,
Util.ToArray(optionalParameterTypes),
null);
884 public MethodToken __GetMethodToken(
MethodInfo method,
Type[] optionalParameterTypes, CustomModifiers[] customModifiers)
887 method.MethodSignature.WriteMethodRef(
this, sig, optionalParameterTypes, customModifiers);
890 record.Class = method.Module ==
this ? method.MetadataToken : GetTypeTokenForMemberRef(method.DeclaringType ?? method.Module.GetModuleType());
891 record.Name = GetOrAddString(method.Name);
892 record.Signature = GetOrAddBlob(sig.ToArray());
893 return new MethodToken(MetadataTokens.GetToken(MetadataTokens.MemberReferenceHandle(
MemberRefTable.FindOrAddRecord(record))));
898 internal MethodToken GetMethodTokenForIL(
MethodInfo method)
900 if (method.IsGenericMethodDefinition)
901 method = method.MakeGenericMethod(method.GetGenericArguments());
903 if (IsFromGenericTypeDefinition(method))
904 return new MethodToken(method.ImportTo(
this));
906 return GetMethodToken(method);
909 internal int GetMethodTokenWinRT(
MethodInfo method)
911 return asm.IsWindowsRuntime ? method.ImportTo(
this) : GetMethodToken(method).Token;
916 return GetMethodToken(constructor.GetMethodInfo());
919 public MethodToken GetConstructorToken(
ConstructorInfo constructor, IEnumerable<Type> optionalParameterTypes)
921 return GetMethodToken(constructor.GetMethodInfo(), optionalParameterTypes);
924 public MethodToken __GetConstructorToken(
ConstructorInfo constructor,
Type[] optionalParameterTypes, CustomModifiers[] customModifiers)
926 return __GetMethodToken(constructor.GetMethodInfo(), optionalParameterTypes, customModifiers);
929 internal int ImportMethodOrField(
Type declaringType,
string name,
Signature sig)
931 var key =
new MemberRefKey(declaringType, name, sig);
932 if (!importedMemberRefs.TryGetValue(key, out var token))
935 rec.Class = GetTypeTokenForMemberRef(declaringType);
936 rec.Name = GetOrAddString(name);
939 rec.Signature = GetOrAddBlob(bb.ToArray());
940 token = MetadataTokens.GetToken(MetadataTokens.MemberReferenceHandle(
MemberRefTable.AddRecord(rec)));
941 importedMemberRefs.Add(key, token);
947 internal int ImportMethodSpec(
Type declaringType,
MethodInfo method,
Type[] genericParameters)
949 Debug.Assert(method.__IsMissing || method.GetMethodOnTypeDefinition() == method);
951 var key =
new MethodSpecKey(declaringType, method.Name, method.MethodSignature, genericParameters);
952 if (!importedMethodSpecs.TryGetValue(key, out var token))
955 var mb = method as MethodBuilder;
956 if (mb !=
null && mb.ModuleBuilder ==
this && !declaringType.IsGenericType)
958 rec.Method = mb.MetadataToken;
964 rec.Method = ImportMethodOrField(declaringType, method.Name, method.MethodSignature);
968 Signature.WriteMethodSpec(
this, spec, genericParameters);
969 rec.Instantiation = GetOrAddBlob(spec.ToArray());
970 token = MetadataTokens.GetToken(MetadataTokens.MethodSpecificationHandle(
MethodSpecTable.FindOrAddRecord(rec)));
971 importedMethodSpecs.Add(key, token);
977 internal int ImportType(
Type type)
979 if (typeTokens.TryGetValue(type, out var token) ==
false)
981 if (type.HasElementType || type.IsConstructedGenericType || type.IsFunctionPointer)
984 Signature.WriteTypeSpec(
this, spec, type);
985 token = MetadataTokens.GetToken(MetadataTokens.TypeSpecificationHandle(
TypeSpecTable.AddRecord(GetOrAddBlob(spec.ToArray()))));
991 rec.ResolutionScope = GetTypeToken(type.DeclaringType).Token;
992 else if (type.Module ==
this)
993 rec.ResolutionScope = 1;
995 rec.ResolutionScope = ImportAssemblyRef(type.Assembly);
997 SetTypeNameAndTypeNamespace(type.TypeName, out rec.TypeName, out rec.TypeNamespace);
998 token = MetadataTokens.GetToken(MetadataTokens.TypeReferenceHandle(
TypeRefTable.AddRecord(rec)));
1001 typeTokens.Add(type, token);
1007 int ImportAssemblyRef(
Assembly asm)
1009 if (referencedAssemblies.TryGetValue(
asm, out var token) ==
false)
1013 token = AllocPseudoToken();
1014 referencedAssemblies.Add(
asm, token);
1020 internal void FillAssemblyRefTable()
1022 foreach (var kv
in referencedAssemblies)
1023 if (IsPseudoToken(kv.Value))
1024 RegisterTokenFixup(kv.Value, FindOrAddAssemblyRef(kv.Key.GetName(),
false));
1027 private int FindOrAddAssemblyRef(
AssemblyName name,
bool alwaysAdd)
1030 var ver = name.Version ??
new Version(0, 0, 0, 0);
1031 rec.MajorVersion = (ushort)ver.Major;
1032 rec.MinorVersion = (ushort)ver.Minor;
1033 rec.BuildNumber = (ushort)ver.Build;
1034 rec.RevisionNumber = (ushort)ver.Revision;
1035 rec.Flags = (int)(name.Flags & ~AssemblyNameFlags.PublicKey);
1036 const AssemblyNameFlags afPA_Specified = (AssemblyNameFlags)0x0080;
1037 const AssemblyNameFlags afPA_Mask = (AssemblyNameFlags)0x0070;
1038 if ((name.RawFlags & afPA_Specified) != 0)
1040 rec.Flags |= (int)(name.RawFlags & afPA_Mask);
1042 if (name.ContentType == AssemblyContentType.WindowsRuntime)
1044 rec.Flags |= 0x0200;
1046 byte[] publicKeyOrToken =
null;
1047 if (usePublicKeyAssemblyReference)
1049 publicKeyOrToken = name.GetPublicKey();
1051 if (publicKeyOrToken ==
null || publicKeyOrToken.Length == 0)
1053 publicKeyOrToken = name.GetPublicKeyToken() ?? Array.Empty<
byte>();
1057 const int PublicKey = 0x0001;
1058 rec.Flags |= PublicKey;
1060 rec.PublicKeyOrToken = GetOrAddBlob(publicKeyOrToken);
1061 rec.Name = GetOrAddString(name.Name);
1062 rec.Culture = name.CultureName ==
null ? default : GetOrAddString(name.CultureName);
1063 if (name.hash !=
null)
1065 rec.HashValue = GetOrAddBlob(name.hash);
1069 rec.HashValue =
default;
1072 return MetadataTokens.GetToken(MetadataTokens.AssemblyReferenceHandle(alwaysAdd ?
AssemblyRefTable.AddRecord(rec) :
AssemblyRefTable.FindOrAddRecord(rec)));
1075 internal void RegisterTokenFixup(
int pseudoToken,
int realToken)
1077 int index = -(pseudoToken + 1);
1078 while (resolvedTokens.Count <= index)
1079 resolvedTokens.Add(0);
1081 resolvedTokens[index] = realToken;
1084 internal static bool IsPseudoToken(
int token)
1089 internal int ResolvePseudoToken(
int pseudoToken)
1091 return IsPseudoToken(pseudoToken) ? resolvedTokens[-(pseudoToken + 1)] : pseudoToken;
1094 internal void FixupMethodBodyTokens()
1096 int methodToken = 0x06000001;
1097 int fieldToken = 0x04000001;
1098 int parameterToken = 0x08000001;
1100 foreach (var type
in types)
1101 type.ResolveMethodAndFieldTokens(
ref methodToken,
ref fieldToken,
ref parameterToken);
1107 internal void WriteMetadata()
1109 foreach (var table
in GetTables())
1114 static int StringToPaddedUTF8Length(
string str)
1116 return (
System.
Text.Encoding.UTF8.GetByteCount(str) + 4) & ~3;
1119 static byte[] StringToPaddedUTF8(
string str)
1121 byte[] buf =
new byte[(
System.
Text.Encoding.UTF8.GetByteCount(str) + 4) & ~3];
1122 System.
Text.Encoding.UTF8.GetBytes(str, 0, str.Length, buf, 0);
1126 internal override void ExportTypes(AssemblyFileHandle fileToken, ModuleBuilder manifestModule)
1128 manifestModule.ExportTypes(types.ToArray(), fileToken);
1131 internal void ExportTypes(
Type[] types, AssemblyFileHandle fileToken)
1133 var declaringTypes =
new Dictionary<Type, ExportedTypeHandle>();
1135 foreach (var type
in types)
1137 if (type.IsModulePseudoType ==
false && IsVisible(type))
1140 rec.Flags = (int)type.Attributes;
1142 rec.TypeDefId = type.MetadataToken;
1143 SetTypeNameAndTypeNamespace(type.TypeName, out rec.TypeName, out rec.TypeNamespace);
1146 rec.Implementation = MetadataTokens.GetToken(declaringTypes[type.DeclaringType]);
1148 rec.Implementation = MetadataTokens.GetToken(fileToken);
1150 var exportTypeToken = MetadataTokens.ExportedTypeHandle(
ExportedTypeTable.AddRecord(rec));
1151 declaringTypes.Add(type, exportTypeToken);
1156 static bool IsVisible(
Type type)
1159 return type.IsPublic || ((type.IsNestedFamily || type.IsNestedFamORAssem || type.IsNestedPublic) && IsVisible(type.DeclaringType));
1162 internal void AddConstant(
int parentToken,
object defaultValue)
1165 rec.Parent = parentToken;
1167 if (defaultValue ==
null)
1169 rec.Type =
Signature.ELEMENT_TYPE_CLASS;
1172 else if (defaultValue is
bool boolValue)
1174 rec.Type =
Signature.ELEMENT_TYPE_BOOLEAN;
1175 val.Write(boolValue ? (
byte)1 : (
byte)0);
1177 else if (defaultValue is
char charValue)
1180 val.Write(charValue);
1182 else if (defaultValue is sbyte sbyteValue)
1185 val.Write(sbyteValue);
1187 else if (defaultValue is
byte byteValue)
1190 val.Write(byteValue);
1192 else if (defaultValue is
short shortValue)
1195 val.Write(shortValue);
1197 else if (defaultValue is ushort ushortValue)
1200 val.Write(ushortValue);
1202 else if (defaultValue is
int intValue)
1205 val.Write(intValue);
1207 else if (defaultValue is uint uintValue)
1210 val.Write(uintValue);
1212 else if (defaultValue is
long longValue)
1215 val.Write(longValue);
1217 else if (defaultValue is ulong ulongValue)
1220 val.Write(ulongValue);
1222 else if (defaultValue is
float floatValue)
1225 val.Write(floatValue);
1227 else if (defaultValue is
double doubleValue)
1230 val.Write(doubleValue);
1232 else if (defaultValue is
string stringValue)
1234 rec.Type =
Signature.ELEMENT_TYPE_STRING;
1235 foreach (var c
in stringValue)
1238 else if (defaultValue is DateTime dateTimeValue)
1241 val.Write(dateTimeValue.Ticks);
1245 throw new ArgumentException();
1250 rec.Offset = GetOrAddBlob(val.ToArray());
1251 rec.Value = defaultValue;
1255 ModuleBuilder ITypeOwner.ModuleBuilder
1257 get {
return this; }
1264 throw new NotImplementedException();
1266 return types[(metadataToken & 0xFFFFFF) - 1];
1269 public override MethodBase ResolveMethod(
int metadataToken,
Type[] genericTypeArguments,
Type[] genericMethodArguments)
1271 if (genericTypeArguments !=
null || genericMethodArguments !=
null)
1273 throw new NotImplementedException();
1278 foreach (KeyValuePair<MemberRefKey, int> kv
in importedMemberRefs)
1280 if (kv.Value == metadataToken)
1282 return kv.Key.LookupMethod();
1287 if ((metadataToken & 0xFF000000) == 0x06000000)
1289 metadataToken = -(metadataToken & 0x00FFFFFF);
1291 foreach (
Type type
in types)
1293 MethodBase method = ((TypeBuilder)type).LookupMethod(metadataToken);
1299 return ((TypeBuilder)moduleType).LookupMethod(metadataToken);
1302 public override FieldInfo ResolveField(
int metadataToken,
Type[] genericTypeArguments,
Type[] genericMethodArguments)
1304 throw new NotImplementedException();
1307 public override MemberInfo ResolveMember(
int metadataToken,
Type[] genericTypeArguments,
Type[] genericMethodArguments)
1309 throw new NotImplementedException();
1312 public override string ResolveString(
int metadataToken)
1314 throw new NotImplementedException();
1317 public override string FullyQualifiedName => Path.GetFullPath(Path.Combine(
asm.dir, fileName));
1319 public override string Name => fileName;
1321 internal Guid GetModuleVersionIdOrEmpty()
1326 internal ReservedBlob<GuidHandle> GetModuleVersionIdFixup()
1331 public override Guid ModuleVersionId
1336 if (mvid == Guid.Empty && Universe.Deterministic)
1337 throw new InvalidOperationException();
1343 public void __SetModuleVersionId(Guid guid)
1345 if (guid == Guid.Empty && Universe.Deterministic)
1348 throw new ArgumentOutOfRangeException();
1353 internal uint GetTimeDateStamp()
1358 public DateTime __PEHeaderTimeDateStamp
1360 get {
return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(timestamp); }
1363 if (value <
new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc) || value >
new DateTime(2106, 2, 7, 6, 28, 15, DateTimeKind.Utc))
1365 throw new ArgumentOutOfRangeException();
1367 timestamp = (uint)(value -
new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
1371 public override Type[] __ResolveOptionalParameterTypes(
int metadataToken,
Type[] genericTypeArguments,
Type[] genericMethodArguments, out CustomModifiers[] customModifiers)
1373 throw new NotImplementedException();
1376 public override string ScopeName
1378 get {
return moduleName; }
1385 public ISymbolWriter GetSymWriter()
1387 return symbolWriter;
1394 public void DefineUnmanagedResource(
byte[] resource)
1396 throw new NotImplementedException();
1403 public void DefineUnmanagedResource(
string resourceFileName)
1406 nativeResources.ImportWin32ResourceFile(
System.IO.File.ReadAllBytes(resourceFileName));
1409 public bool IsTransient()
1414 public StringToken GetStringConstant(
string str)
1416 return new StringToken(MetadataTokens.GetHeapOffset(metadata.GetOrAddUserString(str)) | (0x70 << 24));
1419 public SignatureToken GetSignatureToken(SignatureHelper sigHelper)
1424 public SignatureToken GetSignatureToken(
byte[] sigBytes,
int sigLength)
1426 var bb =
new BlobBuilder();
1427 bb.WriteBytes(sigBytes, 0, sigLength);
1431 public unsafe SignatureToken GetSignatureToken(Span<byte> sigBytes)
1433 fixed (
byte* b = sigBytes)
1435 var bb =
new BlobBuilder();
1436 bb.WriteBytes(b, sigBytes.Length);
1441 public MethodInfo GetArrayMethod(
Type arrayClass,
string methodName, CallingConventions callingConvention,
Type returnType,
Type[] parameterTypes)
1443 return new ArrayMethod(
this, arrayClass, methodName, callingConvention, returnType, parameterTypes);
1446 public MethodToken GetArrayMethodToken(
Type arrayClass,
string methodName, CallingConventions callingConvention,
Type returnType,
Type[] parameterTypes)
1448 return GetMethodToken(GetArrayMethod(arrayClass, methodName, callingConvention, returnType, parameterTypes));
1451 internal override Type GetModuleType()
1456 internal BlobHandle GetSignatureBlobIndex(
Signature sig)
1459 sig.Write(
this, bb);
1460 return GetOrAddBlob(bb.ToArray());
1464 public new ulong __ImageBase
1466 get {
return imageBaseAddress; }
1467 set { imageBaseAddress = value; }
1470 protected override ulong GetImageBaseImpl()
1472 return imageBaseAddress;
1475 public new ulong __StackReserve
1477 get {
return stackReserve; }
1478 set { stackReserve = value; }
1481 protected override ulong GetStackReserveImpl()
1483 return stackReserve;
1486 public new uint __FileAlignment
1488 get {
return fileAlignment; }
1489 set { fileAlignment = value; }
1492 protected override uint GetFileAlignmentImpl()
1494 return fileAlignment;
1497 public new DllCharacteristics __DllCharacteristics
1499 get {
return dllCharacteristics; }
1500 set { dllCharacteristics = value; }
1503 protected override DllCharacteristics GetDllCharacteristicsImpl()
1505 return dllCharacteristics;
1508 public override int MDStreamVersion
1510 get {
return asm.mdStreamVersion; }
1513 private int AddTypeRefByName(
int resolutionScope,
string ns,
string name)
1516 rec.ResolutionScope = resolutionScope;
1517 SetTypeNameAndTypeNamespace(
new TypeName(ns, name), out rec.TypeName, out rec.TypeNamespace);
1526 public void __Save(PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1528 __Save(
null,
null, portableExecutableKind, imageFileMachine);
1537 public void __Save(Stream peStream, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1539 __Save(peStream,
null, portableExecutableKind, imageFileMachine);
1549 public void __Save(Stream peStream, Stream pdbStream, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1551 SaveImpl(peStream, pdbStream, portableExecutableKind, imageFileMachine);
1562 void SaveImpl(Stream peStream, Stream pdbStream, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1564 if (peStream !=
null && peStream.CanWrite ==
false)
1565 throw new ArgumentException(
"PE stream must support write.", nameof(peStream));
1566 if (pdbStream !=
null && pdbStream.CanWrite ==
false)
1567 throw new ArgumentException(
"PDB stream must support write.", nameof(pdbStream));
1570 PopulatePropertyAndEventTables();
1572 var attributes =
asm.GetCustomAttributesData(
null);
1573 if (attributes.Count > 0)
1575 var mscorlib = ImportAssemblyRef(Universe.CoreLib);
1576 var placeholderTokens =
new int[4];
1577 var placeholderTypeNames =
new string[] {
"AssemblyAttributesGoHere",
"AssemblyAttributesGoHereM",
"AssemblyAttributesGoHereS",
"AssemblyAttributesGoHereSM" };
1579 foreach (var cad
in attributes)
1582 if (cad.Constructor.DeclaringType.BaseType == Universe.System_Security_Permissions_CodeAccessSecurityAttribute)
1584 if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute)
1589 else if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute)
1598 if (placeholderTokens[index] == 0)
1601 placeholderTokens[index] = AddTypeRefByName(mscorlib,
"System.Runtime.CompilerServices", placeholderTypeNames[index]);
1604 SetCustomAttribute(placeholderTokens[index], cad.__ToBuilder());
1608 FillAssemblyRefTable();
1609 ModuleWriter.WriteModule(
null,
null,
this, PEFileKinds.Dll, portableExecutableKind, imageFileMachine, nativeResources,
default,
null, peStream,
null, pdbStream);
1612 public void __AddAssemblyReference(
AssemblyName assemblyName)
1614 __AddAssemblyReference(assemblyName,
null);
1619 referencedAssemblyNames ??=
new List<AssemblyName>();
1620 referencedAssemblyNames.Add((
AssemblyName)assemblyName.Clone());
1621 var token = FindOrAddAssemblyRef(assemblyName,
true);
1622 if (assembly !=
null)
1623 referencedAssemblies.Add(assembly, token);
1626 public override AssemblyName[] __GetReferencedAssemblies()
1628 var list =
new List<AssemblyName>();
1629 if (referencedAssemblyNames !=
null)
1630 foreach (var name
in referencedAssemblyNames)
1631 if (list.Contains(name) ==
false)
1634 foreach (var
asm in referencedAssemblies.Keys)
1636 var name =
asm.GetName();
1637 if (list.Contains(name) ==
false)
1641 return list.ToArray();
1644 public void __AddModuleReference(
string module)
1646 ModuleRefTable.FindOrAddRecord(module ==
null ?
default : GetOrAddString(module));
1649 public override string[] __GetReferencedModules()
1652 for (
int i = 0; i < arr.Length; i++)
1658 public override Type[] __GetReferencedTypes()
1660 var list =
new List<Type>();
1661 foreach (var kv
in typeTokens)
1665 return list.ToArray();
1668 public override Type[] __GetExportedTypes()
1670 throw new NotImplementedException();
1673 public int __AddModule(
int flags,
string name,
byte[] hash)
1677 file.Name = GetOrAddString(name);
1678 file.HashValue = GetOrAddBlob(hash);
1679 return MetadataTokens.GetToken(MetadataTokens.AssemblyFileHandle(
FileTable.AddRecord(file)));
1682 public int __AddManifestResource(
int offset, ResourceAttributes flags,
string name,
int implementation)
1685 res.Offset = offset;
1686 res.Flags = (int)flags;
1687 res.Name = GetOrAddString(name);
1688 res.Implementation = implementation;
1689 return MetadataTokens.GetToken(MetadataTokens.ManifestResourceHandle(
ManifestResourceTable.AddRecord(res)));
1692 public void __SetCustomAttributeFor(
int token, CustomAttributeBuilder customBuilder)
1694 SetCustomAttribute(token, customBuilder);
1697 internal void SetInterfaceImplementationCustomAttribute(TypeBuilder typeBuilder,
Type interfaceType, CustomAttributeBuilder cab)
1701 interfaceImplCustomAttributes ??=
new List<InterfaceImplCustomAttribute>();
1703 var rec =
new InterfaceImplCustomAttribute();
1704 rec.type = typeBuilder.MetadataToken;
1706 var token = GetTypeToken(interfaceType).Token;
1707 token = (token >> 24)
switch
1709 TypeDefTable.Index => (token & 0xFFFFFF) << 2 | 0,
1711 TypeSpecTable.Index => (token & 0xFFFFFF) << 2 | 2,
1712 _ =>
throw new InvalidOperationException(),
1715 rec.interfaceType = token;
1716 rec.pseudoToken = AllocPseudoToken();
1717 interfaceImplCustomAttributes.Add(rec);
1719 SetCustomAttribute(rec.pseudoToken, cab);
1722 internal void ResolveInterfaceImplPseudoTokens()
1724 if (interfaceImplCustomAttributes !=
null)
1726 foreach (var rec
in interfaceImplCustomAttributes)
1732 RegisterTokenFixup(rec.pseudoToken, MetadataTokens.GetToken(MetadataTokens.InterfaceImplementationHandle(i + 1)));
1740 internal void FixupPseudoToken(
ref int token)
1742 if (IsPseudoToken(token))
1743 token = ResolvePseudoToken(token);
1746 internal void SetIsSaved()
1749 throw new InvalidOperationException();
1754 internal bool IsSaved
1756 get {
return saved; }
IKVM.Reflection.Module Module
IKVM.Reflection.Type Type
IKVM.Reflection.Assembly Assembly
IKVM.Reflection.AssemblyName AssemblyName
IKVM.Reflection.ConstructorInfo ConstructorInfo
IKVM.Reflection.FieldInfo FieldInfo
IKVM.Reflection.MemberInfo MemberInfo
IKVM.Reflection.MethodInfo MethodInfo
IKVM.Reflection.MethodBase MethodBase
global::java.lang.invoke.LambdaForm.Name Name
System.Runtime.InteropServices.CallingConvention CallingConvention
Represents a method signature from IL metadadata.
Implements a ResourceSectionBuilder for writing IKVM reflection resource section data.