IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
ModuleBuilder.cs
Go to the documentation of this file.
1/*
2 Copyright (C) 2008-2015 Jeroen Frijters
3
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19
20 Jeroen Frijters
21 jeroen@frijters.net
22
23*/
24using System;
25using System.Collections.Generic;
26using System.Diagnostics;
27using System.Diagnostics.SymbolStore;
28using System.IO;
29using System.Reflection.Metadata;
30using System.Reflection.Metadata.Ecma335;
31using System.Resources;
32using System.Runtime.InteropServices;
33
38
40{
41
42 internal sealed class ModuleBuilder : Module, ITypeOwner
43 {
44
45 struct ResourceWriterRecord
46 {
47
48 readonly string name;
49 readonly ResourceWriter rw;
50 readonly Stream stream;
51 readonly ResourceAttributes attributes;
52
59 internal ResourceWriterRecord(string name, Stream stream, ResourceAttributes attributes) :
60 this(name, null, stream, attributes)
61 {
62
63 }
64
72 internal ResourceWriterRecord(string name, ResourceWriter rw, Stream stream, ResourceAttributes attributes)
73 {
74 this.name = name;
75 this.rw = rw;
76 this.stream = stream;
77 this.attributes = attributes;
78 }
79
80 internal readonly int GetLength() => 4 + (int)stream.Length;
81
86 internal readonly void Write(ModuleBuilder module)
87 {
88 // write resource to internal stream
89 rw?.Generate();
90
91 // align the start of the resource
92 module.resourceStream.Align(8);
93 var offset = module.resourceStream.Count;
94
95 // resource begins with a length, followed by the data
96 module.resourceStream.WriteInt32((int)stream.Length);
97 stream.Position = 0;
98 var buffer = new byte[8192];
99 int length;
100 while ((length = stream.Read(buffer, 0, buffer.Length)) != 0)
101 module.resourceStream.WriteBytes(buffer, 0, length);
102
103 // add the resource record
104 var rec = new ManifestResourceTable.Record();
105 rec.Offset = offset;
106 rec.Flags = (int)attributes;
107 rec.Name = module.GetOrAddString(name);
108 rec.Implementation = 0;
109 module.ManifestResourceTable.AddRecord(rec);
110 }
111
112 internal readonly void Close()
113 {
114 rw?.Close();
115 }
116
117 }
118
119 internal struct VTableFixups
120 {
121
122 internal uint initializedDataOffset;
123 internal ushort count;
124 internal ushort type;
125
126 internal readonly int SlotWidth => (type & 0x02) == 0 ? 4 : 8;
127
128 }
129
130 struct InterfaceImplCustomAttribute
131 {
132
133 internal int type;
134 internal int interfaceType;
135 internal int pseudoToken;
136
137 }
138
139 readonly struct MemberRefKey : IEquatable<MemberRefKey>
140 {
141
142 readonly Type type;
143 readonly string name;
144 readonly Signature signature;
145
152 internal MemberRefKey(Type type, string name, Signature signature)
153 {
154 this.type = type;
155 this.name = name;
156 this.signature = signature;
157 }
158
159 public bool Equals(MemberRefKey other) => other.type.Equals(type) && other.name == name && other.signature.Equals(signature);
160
161 public override bool Equals(object obj) => obj is MemberRefKey other && Equals(other);
162
163 public override int GetHashCode()
164 {
165 return type.GetHashCode() + name.GetHashCode() + signature.GetHashCode();
166 }
167
168 internal MethodBase LookupMethod()
169 {
170 return type.FindMethod(name, (MethodSignature)signature);
171 }
172
173 }
174
175 readonly struct MethodSpecKey : IEquatable<MethodSpecKey>
176 {
177
178 readonly Type type;
179 readonly string name;
180 readonly MethodSignature signature;
181 readonly Type[] genericParameters;
182
190 internal MethodSpecKey(Type type, string name, MethodSignature signature, Type[] genericParameters)
191 {
192 this.type = type;
193 this.name = name;
194 this.signature = signature;
195 this.genericParameters = genericParameters;
196 }
197
198 public bool Equals(MethodSpecKey other)
199 {
200 return other.type.Equals(type) && other.name == name && other.signature.Equals(signature) && Util.ArrayEquals(other.genericParameters, genericParameters);
201 }
202
203 public override bool Equals(object obj) => obj is MethodSpecKey other && Equals(other);
204
205 public override int GetHashCode() => type.GetHashCode() + name.GetHashCode() + signature.GetHashCode() + Util.GetHashCode(genericParameters);
206
207 }
208
209 static readonly bool usePublicKeyAssemblyReference = false;
210
211 readonly MetadataBuilder metadata;
212 readonly BlobBuilder ilStream;
213 readonly MethodBodyStreamEncoder methodBodyEncoder;
214 readonly BlobBuilder resourceStream;
215 readonly AssemblyBuilder asm;
216 Guid mvid;
217 ReservedBlob<GuidHandle> mvidFixup;
218 uint timestamp;
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);
231 internal ModuleResourceSectionBuilder nativeResources;
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;
239
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>();
244 bool saved;
245
253 internal ModuleBuilder(AssemblyBuilder asm, string moduleName, string fileName) :
254 base(asm.Universe)
255 {
256 this.metadata = new MetadataBuilder();
257 this.ilStream = new BlobBuilder();
258 this.methodBodyEncoder = new MethodBodyStreamEncoder(ilStream);
259 this.resourceStream = new BlobBuilder();
260
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;
265
266 if (Universe.Deterministic == false)
267 {
268 __PEHeaderTimeDateStamp = DateTime.UtcNow;
269 mvid = Guid.NewGuid();
270 }
271
272 // add module
273 mvidFixup = metadata.ReserveGuid();
274 ModuleTable.Add(0, GetOrAddString(moduleName), mvidFixup.Handle, default, default);
275
276 // <Module> must be the first record in the TypeDef table
277 moduleType = new TypeBuilder(this, null, "<Module>");
278 types.Add(moduleType);
279 }
280
284 internal MetadataBuilder Metadata => metadata;
285
289 internal BlobBuilder ILStream => ilStream;
290
294 internal MethodBodyStreamEncoder MethodBodyEncoder => methodBodyEncoder;
295
299 internal BlobBuilder InitializedDataStream => initializedDataStream;
300
304 internal BlobBuilder ResourceStream => resourceStream;
305
311 internal StringHandle GetOrAddString(string value)
312 {
313 var h = metadata.GetOrAddString(value);
314 strings[h] = value;
315 return h;
316 }
317
323 internal override string GetString(StringHandle handle) => strings.TryGetValue(handle, out var value) ? value : throw new InvalidOperationException();
324
330 internal BlobHandle GetOrAddBlob(BlobBuilder value)
331 {
332 var h = metadata.GetOrAddBlob(value);
333 blobs[h] = value;
334 return h;
335 }
336
342 internal BlobHandle GetOrAddBlob(byte[] value)
343 {
344 var b = new BlobBuilder();
345 b.WriteBytes(value);
346 return GetOrAddBlob(b);
347 }
348
354 internal BlobHandle GetOrAddBlobUTF8(string value)
355 {
356 return metadata.GetOrAddBlobUTF8(value);
357 }
358
364 internal BlobBuilder GetBlob(BlobHandle handle) => blobs.TryGetValue(handle, out var value) ? value : throw new InvalidOperationException();
365
371 internal override ByteReader GetBlobReader(BlobHandle handle)
372 {
373 var b = GetBlob(handle).ToArray();
374 return new ByteReader(b, 0, b.Length);
375 }
376
381 internal void SetSymWriter(ISymbolWriter writer)
382 {
383 this.symbolWriter = writer;
384 }
385
386 internal void PopulatePropertyAndEventTables()
387 {
388 // LAMESPEC the PropertyMap and EventMap tables are not required to be sorted by the CLI spec,
389 // but .NET sorts them and Mono requires them to be sorted, so we have to populate the
390 // tables in the right order
391 foreach (var type in types)
392 type.PopulatePropertyAndEventTables();
393 }
394
395 internal void WriteTypeDefTable()
396 {
397 int fieldList = 1;
398 int methodList = 1;
399 foreach (var type in types)
400 type.WriteTypeDefRecord(ref fieldList, ref methodList);
401 }
402
403 internal void WriteMethodDefTable()
404 {
405 int paramList = 1;
406 foreach (var type in types)
407 type.WriteMethodDefRecords(ref paramList);
408 }
409
410 internal void WriteParamTable()
411 {
412 foreach (var type in types)
413 type.WriteParamRecords();
414 }
415
416 internal void WriteFieldTable()
417 {
418 foreach (var type in types)
419 type.WriteFieldRecords();
420 }
421
422 internal int AllocPseudoToken()
423 {
424 return nextPseudoToken--;
425 }
426
427 public TypeBuilder DefineType(string name)
428 {
429 return DefineType(name, TypeAttributes.Class);
430 }
431
432 public TypeBuilder DefineType(string name, TypeAttributes attr)
433 {
434 return DefineType(name, attr, null);
435 }
436
437 public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent)
438 {
439 return DefineType(name, attr, parent, PackingSize.Unspecified, 0);
440 }
441
442 public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, int typesize)
443 {
444 return DefineType(name, attr, parent, PackingSize.Unspecified, typesize);
445 }
446
447 public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packsize)
448 {
449 return DefineType(name, attr, parent, packsize, 0);
450 }
451
452 public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, Type[] interfaces)
453 {
454 var tb = DefineType(name, attr, parent);
455 foreach (Type iface in interfaces)
456 tb.AddInterfaceImplementation(iface);
457
458 return tb;
459 }
460
461 public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize)
462 {
463 string ns = null;
464 int lastdot = name.LastIndexOf('.');
465 if (lastdot > 0)
466 {
467 ns = name.Substring(0, lastdot);
468 name = name.Substring(lastdot + 1);
469 }
470
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);
476
477 return typeBuilder;
478 }
479
480 public TypeBuilder __DefineType(string ns, string name)
481 {
482 return DefineType(this, ns, name);
483 }
484
485 internal TypeBuilder DefineType(ITypeOwner owner, string ns, string name)
486 {
487 var typeBuilder = new TypeBuilder(owner, ns, name);
488 types.Add(typeBuilder);
489 return typeBuilder;
490 }
491
492 public EnumBuilder DefineEnum(string name, TypeAttributes visibility, Type underlyingType)
493 {
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);
497 }
498
499 public FieldBuilder __DefineField(string name, Type type, CustomModifiers customModifiers, FieldAttributes attributes)
500 {
501 return moduleType.__DefineField(name, type, customModifiers, attributes);
502 }
503
504 [Obsolete("Please use __DefineField(string, Type, CustomModifiers, FieldAttributes) instead.")]
505 public FieldBuilder __DefineField(string name, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes)
506 {
507 return moduleType.DefineField(name, type, requiredCustomModifiers, optionalCustomModifiers, attributes);
508 }
509
510 public ConstructorBuilder __DefineModuleInitializer(MethodAttributes visibility)
511 {
512 return moduleType.DefineConstructor(visibility | MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, Type.EmptyTypes);
513 }
514
515 public FieldBuilder DefineUninitializedData(string name, int size, FieldAttributes attributes)
516 {
517 return moduleType.DefineUninitializedData(name, size, attributes);
518 }
519
520 public FieldBuilder DefineInitializedData(string name, byte[] data, FieldAttributes attributes)
521 {
522 return moduleType.DefineInitializedData(name, data, attributes);
523 }
524
525 public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)
526 {
527 return moduleType.DefineMethod(name, attributes, returnType, parameterTypes);
528 }
529
530 public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
531 {
532 return moduleType.DefineMethod(name, attributes, callingConvention, returnType, parameterTypes);
533 }
534
535 public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
536 {
537 return moduleType.DefineMethod(name, attributes, callingConvention, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
538 }
539
540 public MethodBuilder DefinePInvokeMethod(string name, string dllName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
541 {
542 return moduleType.DefinePInvokeMethod(name, dllName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
543 }
544
545 public MethodBuilder DefinePInvokeMethod(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
546 {
547 return moduleType.DefinePInvokeMethod(name, dllName, entryName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
548 }
549
550 public void CreateGlobalFunctions()
551 {
552 moduleType.CreateType();
553 }
554
555 internal void AddTypeForwarder(Type type, bool includeNested)
556 {
557 ExportType(type);
558
559 if (includeNested && !type.__IsMissing)
560 {
561 foreach (var nested in type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic))
562 {
563 // we export all nested types (i.e. even the private ones)
564 // (this behavior is the same as the C# compiler)
565 AddTypeForwarder(nested, true);
566 }
567 }
568 }
569
570 int ExportType(Type type)
571 {
572 var rec = new ExportedTypeTable.Record();
573 if (asm.ImageRuntimeVersion == "v2.0.50727")
574 {
575 // HACK we should *not* set the TypeDefId in this case, but 2.0 and 3.5 peverify gives a warning if it is missing (4.5 doesn't)
576 rec.TypeDefId = type.MetadataToken;
577 }
578
579 SetTypeNameAndTypeNamespace(type.TypeName, out rec.TypeName, out rec.TypeNamespace);
580 if (type.IsNested)
581 {
582 rec.Flags = 0;
583 rec.Implementation = ExportType(type.DeclaringType);
584 }
585 else
586 {
587 rec.Flags = 0x00200000; // CorTypeAttr.tdForwarder
588 rec.Implementation = ImportAssemblyRef(type.Assembly);
589 }
590
591 return 0x27000000 | ExportedTypeTable.FindOrAddRecord(rec);
592 }
593
594 void SetTypeNameAndTypeNamespace(TypeName name, out StringHandle typeName, out StringHandle typeNamespace)
595 {
596 typeName = GetOrAddString(name.Name);
597 typeNamespace = name.Namespace == null ? default : GetOrAddString(name.Namespace);
598 }
599
600 public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
601 {
602 SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
603 }
604
605 public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
606 {
607 SetCustomAttribute(0x00000001, customBuilder);
608 }
609
610 internal void SetCustomAttribute(int token, CustomAttributeBuilder customBuilder)
611 {
612 var rec = new CustomAttributeTable.Record();
613 rec.Parent = token;
614 rec.Constructor = asm.IsWindowsRuntime ? customBuilder.Constructor.ImportTo(this) : GetConstructorToken(customBuilder.Constructor).Token;
615 rec.Value = customBuilder.WriteBlob(this);
616 CustomAttributeTable.AddRecord(rec);
617 }
618
619 void AddDeclSecurityRecord(int token, int action, BlobHandle blob)
620 {
621 var rec = new DeclSecurityTable.Record();
622 rec.Action = (short)action;
623 rec.Parent = token;
624 rec.PermissionSet = blob;
625 DeclSecurityTable.AddRecord(rec);
626 }
627
628 internal void AddDeclarativeSecurity(int token, System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet)
629 {
630 AddDeclSecurityRecord(token, (int)securityAction, GetOrAddBlob(System.Text.Encoding.Unicode.GetBytes(permissionSet.ToXml().ToString())));
631 }
632
633 internal void AddDeclarativeSecurity(int token, List<CustomAttributeBuilder> declarativeSecurity)
634 {
635 var ordered = new Dictionary<int, List<CustomAttributeBuilder>>();
636 foreach (var cab in declarativeSecurity)
637 {
638 int action;
639 // check for HostProtectionAttribute without SecurityAction
640 if (cab.ConstructorArgumentCount == 0)
641 {
642 action = (int)System.Security.Permissions.SecurityAction.LinkDemand;
643 }
644 else
645 {
646 action = (int)cab.GetConstructorArgument(0);
647 }
648
649 if (cab.IsLegacyDeclSecurity)
650 {
651 AddDeclSecurityRecord(token, action, cab.WriteLegacyDeclSecurityBlob(this));
652 continue;
653 }
654
655 if (!ordered.TryGetValue(action, out var list))
656 {
657 list = new List<CustomAttributeBuilder>();
658 ordered.Add(action, list);
659 }
660
661 list.Add(cab);
662 }
663
664 foreach (KeyValuePair<int, List<CustomAttributeBuilder>> kv in ordered)
665 AddDeclSecurityRecord(token, kv.Key, WriteDeclSecurityBlob(kv.Value));
666 }
667
668 BlobHandle WriteDeclSecurityBlob(List<CustomAttributeBuilder> list)
669 {
670 var namedArgs = new ByteBuffer(100);
671 var bb = new ByteBuffer(list.Count * 100);
672 bb.Write((byte)'.');
673 bb.WriteCompressedUInt(list.Count);
674 foreach (var cab in list)
675 {
676 bb.Write(cab.Constructor.DeclaringType.AssemblyQualifiedName);
677 namedArgs.Clear();
678 cab.WriteNamedArgumentsForDeclSecurity(this, namedArgs);
679 bb.WriteCompressedUInt(namedArgs.Length);
680 bb.Write(namedArgs);
681 }
682
683 return GetOrAddBlob(bb.ToArray());
684 }
685
686 public void DefineManifestResource(string name, Stream stream, ResourceAttributes attribute)
687 {
688 resourceWriters.Add(new ResourceWriterRecord(name, stream, attribute));
689 }
690
691 public IResourceWriter DefineResource(string name, string description)
692 {
693 return DefineResource(name, description, ResourceAttributes.Public);
694 }
695
696 public IResourceWriter DefineResource(string name, string description, ResourceAttributes attribute)
697 {
698 // FXBUG we ignore the description, because there is no such thing
699 var mem = new MemoryStream();
700 var rw = new ResourceWriter(mem);
701 resourceWriters.Add(new ResourceWriterRecord(name, rw, mem, attribute));
702 return rw;
703 }
704
709 internal void WriteResources()
710 {
711 foreach (var rwr in resourceWriters)
712 {
713 rwr.Write(this);
714 rwr.Close();
715 }
716 }
717
718 public override Assembly Assembly
719 {
720 get { return asm; }
721 }
722
723 internal override Type FindType(TypeName name)
724 {
725 foreach (var type in types)
726 if (type.TypeName == name)
727 return type;
728
729 return null;
730 }
731
732 internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
733 {
734 foreach (var type in types)
735 if (type.TypeName.ToLowerInvariant() == lowerCaseName)
736 return type;
737
738 return null;
739 }
740
741 internal override void GetTypesImpl(List<Type> list)
742 {
743 foreach (var type in types)
744 if (type != moduleType)
745 list.Add(type);
746 }
747
748 public ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType)
749 {
750 if (symbolWriter != null)
751 return symbolWriter.DefineDocument(url, language, languageVendor, documentType);
752 else
753 throw new NotSupportedException();
754 }
755
762 public void SetUserEntryPoint(MethodInfo entryPoint)
763 {
764 // Set the user entry point. Compiler may generate startup stub before calling user main.
765 // The startup stub will be the entry point. While the user "main" will be the user entry
766 // point so that debugger will not step into the compiler entry point.
767
768 if (entryPoint == null)
769 throw new ArgumentNullException("entryPoint");
770
771 // Cannot set entry point when it is not a debug module
772 if (symbolWriter == null)
773 throw new InvalidOperationException("Not a debug ModuleBuilder.");
774
775 if (entryPoint.DeclaringType != null)
776 {
777 if (!entryPoint.Module.Equals(this))
778 {
779 // you cannot pass in a MethodInfo that is not contained by this ModuleBuilder
780 throw new InvalidOperationException("The argument passed in was not from the same ModuleBuilder.");
781 }
782 }
783 else
784 {
785 // unfortunately this check is missing for global function passed in as RuntimeMethodInfo.
786 // The problem is that Reflection does not
787 // allow us to get the containing module giving a global function
788 MethodBuilder mb = entryPoint as MethodBuilder;
789 if (mb != null && mb.ModuleBuilder != this)
790 {
791 // you cannot pass in a MethodInfo that is not contained by this ModuleBuilder
792 throw new InvalidOperationException("The argument passed in was not from the same ModuleBuilder.");
793 }
794 }
795
796 // get the metadata token value and create the SymbolStore's token value class
797 SymbolToken tkMethod = new SymbolToken(GetMethodToken(entryPoint).Token);
798
799 // set the UserEntryPoint
800 symbolWriter.SetUserEntryPoint(tkMethod);
801 }
802
803 public int __GetAssemblyToken(Assembly assembly)
804 {
805 return ImportAssemblyRef(assembly);
806 }
807
808 public TypeToken GetTypeToken(string name)
809 {
810 return new TypeToken(GetType(name, true, false).MetadataToken);
811 }
812
813 public TypeToken GetTypeToken(Type type)
814 {
815 if (type.Module == this && !asm.IsWindowsRuntime)
816 return new TypeToken(type.GetModuleBuilderToken());
817 else
818 return new TypeToken(ImportType(type));
819 }
820
821 internal int GetTypeTokenForMemberRef(Type type)
822 {
823 if (type.__IsMissing)
824 {
825 return ImportType(type);
826 }
827 else if (type.IsGenericTypeDefinition)
828 {
829 if (memberRefTypeTokens.TryGetValue(type, out var token) == false)
830 {
831 var spec = new ByteBuffer(5);
832 Signature.WriteTypeSpec(this, spec, type);
833 token = MetadataTokens.GetToken(MetadataTokens.TypeSpecificationHandle(TypeSpecTable.AddRecord(GetOrAddBlob(spec.ToArray()))));
834 memberRefTypeTokens.Add(type, token);
835 }
836 return token;
837 }
838 else if (type.IsModulePseudoType)
839 {
840 return MetadataTokens.GetToken(MetadataTokens.ModuleReferenceHandle(ModuleRefTable.FindOrAddRecord(GetOrAddString(type.Module.ScopeName))));
841 }
842 else
843 {
844 return GetTypeToken(type).Token;
845 }
846 }
847
848 static bool IsFromGenericTypeDefinition(MemberInfo member)
849 {
850 var decl = member.DeclaringType;
851 return decl != null && !decl.__IsMissing && decl.IsGenericTypeDefinition;
852 }
853
854 public FieldToken GetFieldToken(FieldInfo field)
855 {
856 // NOTE for some reason, when TypeBuilder.GetFieldToken() is used on a field in a generic type definition,
857 // a memberref token is returned (confirmed on .NET) unlike for Get(Method|Constructor)Token which always
858 // simply returns the MethodDef token (if the method is from the same module).
859 var fb = field as FieldBuilder;
860 if (fb != null && fb.Module == this && !IsFromGenericTypeDefinition(fb))
861 {
862 return new FieldToken(fb.MetadataToken);
863 }
864 else
865 {
866 return new FieldToken(field.ImportTo(this));
867 }
868 }
869
870 public MethodToken GetMethodToken(MethodInfo method)
871 {
872 var mb = method as MethodBuilder;
873 if (mb != null && mb.ModuleBuilder == this)
874 return new MethodToken(mb.MetadataToken);
875 else
876 return new MethodToken(method.ImportTo(this));
877 }
878
879 public MethodToken GetMethodToken(MethodInfo method, IEnumerable<Type> optionalParameterTypes)
880 {
881 return __GetMethodToken(method, Util.ToArray(optionalParameterTypes), null);
882 }
883
884 public MethodToken __GetMethodToken(MethodInfo method, Type[] optionalParameterTypes, CustomModifiers[] customModifiers)
885 {
886 var sig = new ByteBuffer(16);
887 method.MethodSignature.WriteMethodRef(this, sig, optionalParameterTypes, customModifiers);
888
889 var record = new MemberRefTable.Record();
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))));
894 }
895
896 // when we refer to a method on a generic type definition in the IL stream,
897 // we need to use a MemberRef (even if the method is in the same module)
898 internal MethodToken GetMethodTokenForIL(MethodInfo method)
899 {
900 if (method.IsGenericMethodDefinition)
901 method = method.MakeGenericMethod(method.GetGenericArguments());
902
903 if (IsFromGenericTypeDefinition(method))
904 return new MethodToken(method.ImportTo(this));
905 else
906 return GetMethodToken(method);
907 }
908
909 internal int GetMethodTokenWinRT(MethodInfo method)
910 {
911 return asm.IsWindowsRuntime ? method.ImportTo(this) : GetMethodToken(method).Token;
912 }
913
914 public MethodToken GetConstructorToken(ConstructorInfo constructor)
915 {
916 return GetMethodToken(constructor.GetMethodInfo());
917 }
918
919 public MethodToken GetConstructorToken(ConstructorInfo constructor, IEnumerable<Type> optionalParameterTypes)
920 {
921 return GetMethodToken(constructor.GetMethodInfo(), optionalParameterTypes);
922 }
923
924 public MethodToken __GetConstructorToken(ConstructorInfo constructor, Type[] optionalParameterTypes, CustomModifiers[] customModifiers)
925 {
926 return __GetMethodToken(constructor.GetMethodInfo(), optionalParameterTypes, customModifiers);
927 }
928
929 internal int ImportMethodOrField(Type declaringType, string name, Signature sig)
930 {
931 var key = new MemberRefKey(declaringType, name, sig);
932 if (!importedMemberRefs.TryGetValue(key, out var token))
933 {
934 var rec = new MemberRefTable.Record();
935 rec.Class = GetTypeTokenForMemberRef(declaringType);
936 rec.Name = GetOrAddString(name);
937 var bb = new ByteBuffer(16);
938 sig.Write(this, bb);
939 rec.Signature = GetOrAddBlob(bb.ToArray());
940 token = MetadataTokens.GetToken(MetadataTokens.MemberReferenceHandle(MemberRefTable.AddRecord(rec)));
941 importedMemberRefs.Add(key, token);
942 }
943
944 return token;
945 }
946
947 internal int ImportMethodSpec(Type declaringType, MethodInfo method, Type[] genericParameters)
948 {
949 Debug.Assert(method.__IsMissing || method.GetMethodOnTypeDefinition() == method);
950
951 var key = new MethodSpecKey(declaringType, method.Name, method.MethodSignature, genericParameters);
952 if (!importedMethodSpecs.TryGetValue(key, out var token))
953 {
954 var rec = new MethodSpecTable.Record();
955 var mb = method as MethodBuilder;
956 if (mb != null && mb.ModuleBuilder == this && !declaringType.IsGenericType)
957 {
958 rec.Method = mb.MetadataToken;
959 }
960 else
961 {
962 // we're calling ImportMethodOrField directly here, because 'method' may be a MethodDef on a generic TypeDef and 'declaringType' the type instance
963 // (in order words the method and type have already been decoupled by the caller)
964 rec.Method = ImportMethodOrField(declaringType, method.Name, method.MethodSignature);
965 }
966
967 var spec = new ByteBuffer(10);
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);
972 }
973
974 return token;
975 }
976
977 internal int ImportType(Type type)
978 {
979 if (typeTokens.TryGetValue(type, out var token) == false)
980 {
981 if (type.HasElementType || type.IsConstructedGenericType || type.IsFunctionPointer)
982 {
983 var spec = new ByteBuffer(5);
984 Signature.WriteTypeSpec(this, spec, type);
985 token = MetadataTokens.GetToken(MetadataTokens.TypeSpecificationHandle(TypeSpecTable.AddRecord(GetOrAddBlob(spec.ToArray()))));
986 }
987 else
988 {
989 var rec = new TypeRefTable.Record();
990 if (type.IsNested)
991 rec.ResolutionScope = GetTypeToken(type.DeclaringType).Token;
992 else if (type.Module == this)
993 rec.ResolutionScope = 1;
994 else
995 rec.ResolutionScope = ImportAssemblyRef(type.Assembly);
996
997 SetTypeNameAndTypeNamespace(type.TypeName, out rec.TypeName, out rec.TypeNamespace);
998 token = MetadataTokens.GetToken(MetadataTokens.TypeReferenceHandle(TypeRefTable.AddRecord(rec)));
999 }
1000
1001 typeTokens.Add(type, token);
1002 }
1003
1004 return token;
1005 }
1006
1007 int ImportAssemblyRef(Assembly asm)
1008 {
1009 if (referencedAssemblies.TryGetValue(asm, out var token) == false)
1010 {
1011 // We can't write the AssemblyRef record here yet, because the identity of the assembly can still change
1012 // (if it's an AssemblyBuilder).
1013 token = AllocPseudoToken();
1014 referencedAssemblies.Add(asm, token);
1015 }
1016
1017 return token;
1018 }
1019
1020 internal void FillAssemblyRefTable()
1021 {
1022 foreach (var kv in referencedAssemblies)
1023 if (IsPseudoToken(kv.Value))
1024 RegisterTokenFixup(kv.Value, FindOrAddAssemblyRef(kv.Key.GetName(), false));
1025 }
1026
1027 private int FindOrAddAssemblyRef(AssemblyName name, bool alwaysAdd)
1028 {
1029 var rec = new AssemblyRefTable.Record();
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)
1039 {
1040 rec.Flags |= (int)(name.RawFlags & afPA_Mask);
1041 }
1042 if (name.ContentType == AssemblyContentType.WindowsRuntime)
1043 {
1044 rec.Flags |= 0x0200;
1045 }
1046 byte[] publicKeyOrToken = null;
1047 if (usePublicKeyAssemblyReference)
1048 {
1049 publicKeyOrToken = name.GetPublicKey();
1050 }
1051 if (publicKeyOrToken == null || publicKeyOrToken.Length == 0)
1052 {
1053 publicKeyOrToken = name.GetPublicKeyToken() ?? Array.Empty<byte>();
1054 }
1055 else
1056 {
1057 const int PublicKey = 0x0001;
1058 rec.Flags |= PublicKey;
1059 }
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)
1064 {
1065 rec.HashValue = GetOrAddBlob(name.hash);
1066 }
1067 else
1068 {
1069 rec.HashValue = default;
1070 }
1071
1072 return MetadataTokens.GetToken(MetadataTokens.AssemblyReferenceHandle(alwaysAdd ? AssemblyRefTable.AddRecord(rec) : AssemblyRefTable.FindOrAddRecord(rec)));
1073 }
1074
1075 internal void RegisterTokenFixup(int pseudoToken, int realToken)
1076 {
1077 int index = -(pseudoToken + 1);
1078 while (resolvedTokens.Count <= index)
1079 resolvedTokens.Add(0);
1080
1081 resolvedTokens[index] = realToken;
1082 }
1083
1084 internal static bool IsPseudoToken(int token)
1085 {
1086 return token < 0;
1087 }
1088
1089 internal int ResolvePseudoToken(int pseudoToken)
1090 {
1091 return IsPseudoToken(pseudoToken) ? resolvedTokens[-(pseudoToken + 1)] : pseudoToken;
1092 }
1093
1094 internal void FixupMethodBodyTokens()
1095 {
1096 int methodToken = 0x06000001;
1097 int fieldToken = 0x04000001;
1098 int parameterToken = 0x08000001;
1099
1100 foreach (var type in types)
1101 type.ResolveMethodAndFieldTokens(ref methodToken, ref fieldToken, ref parameterToken);
1102 }
1103
1107 internal void WriteMetadata()
1108 {
1109 foreach (var table in GetTables())
1110 if (table != null)
1111 table.Write(this);
1112 }
1113
1114 static int StringToPaddedUTF8Length(string str)
1115 {
1116 return (System.Text.Encoding.UTF8.GetByteCount(str) + 4) & ~3;
1117 }
1118
1119 static byte[] StringToPaddedUTF8(string str)
1120 {
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);
1123 return buf;
1124 }
1125
1126 internal override void ExportTypes(AssemblyFileHandle fileToken, ModuleBuilder manifestModule)
1127 {
1128 manifestModule.ExportTypes(types.ToArray(), fileToken);
1129 }
1130
1131 internal void ExportTypes(Type[] types, AssemblyFileHandle fileToken)
1132 {
1133 var declaringTypes = new Dictionary<Type, ExportedTypeHandle>();
1134
1135 foreach (var type in types)
1136 {
1137 if (type.IsModulePseudoType == false && IsVisible(type))
1138 {
1139 var rec = new ExportedTypeTable.Record();
1140 rec.Flags = (int)type.Attributes;
1141 // LAMESPEC ECMA says that TypeDefId is a row index, but it should be a token
1142 rec.TypeDefId = type.MetadataToken;
1143 SetTypeNameAndTypeNamespace(type.TypeName, out rec.TypeName, out rec.TypeNamespace);
1144
1145 if (type.IsNested)
1146 rec.Implementation = MetadataTokens.GetToken(declaringTypes[type.DeclaringType]);
1147 else
1148 rec.Implementation = MetadataTokens.GetToken(fileToken);
1149
1150 var exportTypeToken = MetadataTokens.ExportedTypeHandle(ExportedTypeTable.AddRecord(rec));
1151 declaringTypes.Add(type, exportTypeToken);
1152 }
1153 }
1154 }
1155
1156 static bool IsVisible(Type type)
1157 {
1158 // NOTE this is not the same as Type.IsVisible, because that doesn't take into account family access
1159 return type.IsPublic || ((type.IsNestedFamily || type.IsNestedFamORAssem || type.IsNestedPublic) && IsVisible(type.DeclaringType));
1160 }
1161
1162 internal void AddConstant(int parentToken, object defaultValue)
1163 {
1164 var rec = new ConstantTable.Record();
1165 rec.Parent = parentToken;
1166 var val = new ByteBuffer(16);
1167 if (defaultValue == null)
1168 {
1169 rec.Type = Signature.ELEMENT_TYPE_CLASS;
1170 val.Write((int)0);
1171 }
1172 else if (defaultValue is bool boolValue)
1173 {
1174 rec.Type = Signature.ELEMENT_TYPE_BOOLEAN;
1175 val.Write(boolValue ? (byte)1 : (byte)0);
1176 }
1177 else if (defaultValue is char charValue)
1178 {
1179 rec.Type = Signature.ELEMENT_TYPE_CHAR;
1180 val.Write(charValue);
1181 }
1182 else if (defaultValue is sbyte sbyteValue)
1183 {
1184 rec.Type = Signature.ELEMENT_TYPE_I1;
1185 val.Write(sbyteValue);
1186 }
1187 else if (defaultValue is byte byteValue)
1188 {
1189 rec.Type = Signature.ELEMENT_TYPE_U1;
1190 val.Write(byteValue);
1191 }
1192 else if (defaultValue is short shortValue)
1193 {
1194 rec.Type = Signature.ELEMENT_TYPE_I2;
1195 val.Write(shortValue);
1196 }
1197 else if (defaultValue is ushort ushortValue)
1198 {
1199 rec.Type = Signature.ELEMENT_TYPE_U2;
1200 val.Write(ushortValue);
1201 }
1202 else if (defaultValue is int intValue)
1203 {
1204 rec.Type = Signature.ELEMENT_TYPE_I4;
1205 val.Write(intValue);
1206 }
1207 else if (defaultValue is uint uintValue)
1208 {
1209 rec.Type = Signature.ELEMENT_TYPE_U4;
1210 val.Write(uintValue);
1211 }
1212 else if (defaultValue is long longValue)
1213 {
1214 rec.Type = Signature.ELEMENT_TYPE_I8;
1215 val.Write(longValue);
1216 }
1217 else if (defaultValue is ulong ulongValue)
1218 {
1219 rec.Type = Signature.ELEMENT_TYPE_U8;
1220 val.Write(ulongValue);
1221 }
1222 else if (defaultValue is float floatValue)
1223 {
1224 rec.Type = Signature.ELEMENT_TYPE_R4;
1225 val.Write(floatValue);
1226 }
1227 else if (defaultValue is double doubleValue)
1228 {
1229 rec.Type = Signature.ELEMENT_TYPE_R8;
1230 val.Write(doubleValue);
1231 }
1232 else if (defaultValue is string stringValue)
1233 {
1234 rec.Type = Signature.ELEMENT_TYPE_STRING;
1235 foreach (var c in stringValue)
1236 val.Write(c);
1237 }
1238 else if (defaultValue is DateTime dateTimeValue)
1239 {
1240 rec.Type = Signature.ELEMENT_TYPE_I8;
1241 val.Write(dateTimeValue.Ticks);
1242 }
1243 else
1244 {
1245 throw new ArgumentException();
1246 }
1247
1248 // encode index into blobs, as well as pass along value, since SRME does not have an AddConstant override that takes a handle
1249 // final blob should be deduplicated, leading to the same index value on write
1250 rec.Offset = GetOrAddBlob(val.ToArray());
1251 rec.Value = defaultValue;
1252 ConstantTable.AddRecord(rec);
1253 }
1254
1255 ModuleBuilder ITypeOwner.ModuleBuilder
1256 {
1257 get { return this; }
1258 }
1259
1260 internal override Type ResolveType(int metadataToken, IGenericContext context)
1261 {
1262 if (metadataToken >> 24 != TypeDefTable.Index)
1263 {
1264 throw new NotImplementedException();
1265 }
1266 return types[(metadataToken & 0xFFFFFF) - 1];
1267 }
1268
1269 public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1270 {
1271 if (genericTypeArguments != null || genericMethodArguments != null)
1272 {
1273 throw new NotImplementedException();
1274 }
1275 // this method is inefficient, but since it isn't used we don't care
1276 if ((metadataToken >> 24) == MemberRefTable.Index)
1277 {
1278 foreach (KeyValuePair<MemberRefKey, int> kv in importedMemberRefs)
1279 {
1280 if (kv.Value == metadataToken)
1281 {
1282 return kv.Key.LookupMethod();
1283 }
1284 }
1285 }
1286 // HACK if we're given a SymbolToken, we need to convert back
1287 if ((metadataToken & 0xFF000000) == 0x06000000)
1288 {
1289 metadataToken = -(metadataToken & 0x00FFFFFF);
1290 }
1291 foreach (Type type in types)
1292 {
1293 MethodBase method = ((TypeBuilder)type).LookupMethod(metadataToken);
1294 if (method != null)
1295 {
1296 return method;
1297 }
1298 }
1299 return ((TypeBuilder)moduleType).LookupMethod(metadataToken);
1300 }
1301
1302 public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1303 {
1304 throw new NotImplementedException();
1305 }
1306
1307 public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1308 {
1309 throw new NotImplementedException();
1310 }
1311
1312 public override string ResolveString(int metadataToken)
1313 {
1314 throw new NotImplementedException();
1315 }
1316
1317 public override string FullyQualifiedName => Path.GetFullPath(Path.Combine(asm.dir, fileName));
1318
1319 public override string Name => fileName;
1320
1321 internal Guid GetModuleVersionIdOrEmpty()
1322 {
1323 return mvid;
1324 }
1325
1326 internal ReservedBlob<GuidHandle> GetModuleVersionIdFixup()
1327 {
1328 return mvidFixup;
1329 }
1330
1331 public override Guid ModuleVersionId
1332 {
1333 get
1334 {
1335 // if a deterministic GUID is used, it can't be queried before the assembly has been written
1336 if (mvid == Guid.Empty && Universe.Deterministic)
1337 throw new InvalidOperationException();
1338
1339 return mvid;
1340 }
1341 }
1342
1343 public void __SetModuleVersionId(Guid guid)
1344 {
1345 if (guid == Guid.Empty && Universe.Deterministic)
1346 {
1347 // if you want to use Guid.Empty, don't set UniverseOptions.DeterministicOutput
1348 throw new ArgumentOutOfRangeException();
1349 }
1350 mvid = guid;
1351 }
1352
1353 internal uint GetTimeDateStamp()
1354 {
1355 return timestamp;
1356 }
1357
1358 public DateTime __PEHeaderTimeDateStamp
1359 {
1360 get { return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(timestamp); }
1361 set
1362 {
1363 if (value < new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc) || value > new DateTime(2106, 2, 7, 6, 28, 15, DateTimeKind.Utc))
1364 {
1365 throw new ArgumentOutOfRangeException();
1366 }
1367 timestamp = (uint)(value - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
1368 }
1369 }
1370
1371 public override Type[] __ResolveOptionalParameterTypes(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments, out CustomModifiers[] customModifiers)
1372 {
1373 throw new NotImplementedException();
1374 }
1375
1376 public override string ScopeName
1377 {
1378 get { return moduleName; }
1379 }
1380
1385 public ISymbolWriter GetSymWriter()
1386 {
1387 return symbolWriter;
1388 }
1389
1394 public void DefineUnmanagedResource(byte[] resource)
1395 {
1396 throw new NotImplementedException();
1397 }
1398
1403 public void DefineUnmanagedResource(string resourceFileName)
1404 {
1405 nativeResources = new ModuleResourceSectionBuilder();
1406 nativeResources.ImportWin32ResourceFile(System.IO.File.ReadAllBytes(resourceFileName));
1407 }
1408
1409 public bool IsTransient()
1410 {
1411 return false;
1412 }
1413
1414 public StringToken GetStringConstant(string str)
1415 {
1416 return new StringToken(MetadataTokens.GetHeapOffset(metadata.GetOrAddUserString(str)) | (0x70 << 24));
1417 }
1418
1419 public SignatureToken GetSignatureToken(SignatureHelper sigHelper)
1420 {
1421 return new SignatureToken(StandAloneSigTable.FindOrAddRecord(GetOrAddBlob(sigHelper.GetSignature(this).ToArray())) | (StandAloneSigTable.Index << 24));
1422 }
1423
1424 public SignatureToken GetSignatureToken(byte[] sigBytes, int sigLength)
1425 {
1426 var bb = new BlobBuilder();
1427 bb.WriteBytes(sigBytes, 0, sigLength);
1428 return new SignatureToken(StandAloneSigTable.FindOrAddRecord(GetOrAddBlob(bb)) | (StandAloneSigTable.Index << 24));
1429 }
1430
1431 public unsafe SignatureToken GetSignatureToken(Span<byte> sigBytes)
1432 {
1433 fixed (byte* b = sigBytes)
1434 {
1435 var bb = new BlobBuilder();
1436 bb.WriteBytes(b, sigBytes.Length);
1437 return new SignatureToken(StandAloneSigTable.FindOrAddRecord(GetOrAddBlob(bb)) | (StandAloneSigTable.Index << 24));
1438 }
1439 }
1440
1441 public MethodInfo GetArrayMethod(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
1442 {
1443 return new ArrayMethod(this, arrayClass, methodName, callingConvention, returnType, parameterTypes);
1444 }
1445
1446 public MethodToken GetArrayMethodToken(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
1447 {
1448 return GetMethodToken(GetArrayMethod(arrayClass, methodName, callingConvention, returnType, parameterTypes));
1449 }
1450
1451 internal override Type GetModuleType()
1452 {
1453 return moduleType;
1454 }
1455
1456 internal BlobHandle GetSignatureBlobIndex(Signature sig)
1457 {
1458 var bb = new ByteBuffer(16);
1459 sig.Write(this, bb);
1460 return GetOrAddBlob(bb.ToArray());
1461 }
1462
1463 // non-standard API
1464 public new ulong __ImageBase
1465 {
1466 get { return imageBaseAddress; }
1467 set { imageBaseAddress = value; }
1468 }
1469
1470 protected override ulong GetImageBaseImpl()
1471 {
1472 return imageBaseAddress;
1473 }
1474
1475 public new ulong __StackReserve
1476 {
1477 get { return stackReserve; }
1478 set { stackReserve = value; }
1479 }
1480
1481 protected override ulong GetStackReserveImpl()
1482 {
1483 return stackReserve;
1484 }
1485
1486 public new uint __FileAlignment
1487 {
1488 get { return fileAlignment; }
1489 set { fileAlignment = value; }
1490 }
1491
1492 protected override uint GetFileAlignmentImpl()
1493 {
1494 return fileAlignment;
1495 }
1496
1497 public new DllCharacteristics __DllCharacteristics
1498 {
1499 get { return dllCharacteristics; }
1500 set { dllCharacteristics = value; }
1501 }
1502
1503 protected override DllCharacteristics GetDllCharacteristicsImpl()
1504 {
1505 return dllCharacteristics;
1506 }
1507
1508 public override int MDStreamVersion
1509 {
1510 get { return asm.mdStreamVersion; }
1511 }
1512
1513 private int AddTypeRefByName(int resolutionScope, string ns, string name)
1514 {
1515 TypeRefTable.Record rec = new TypeRefTable.Record();
1516 rec.ResolutionScope = resolutionScope;
1517 SetTypeNameAndTypeNamespace(new TypeName(ns, name), out rec.TypeName, out rec.TypeNamespace);
1518 return 0x01000000 | this.TypeRefTable.AddRecord(rec);
1519 }
1520
1526 public void __Save(PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1527 {
1528 __Save(null, null, portableExecutableKind, imageFileMachine);
1529 }
1530
1537 public void __Save(Stream peStream, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1538 {
1539 __Save(peStream, null, portableExecutableKind, imageFileMachine);
1540 }
1541
1549 public void __Save(Stream peStream, Stream pdbStream, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1550 {
1551 SaveImpl(peStream, pdbStream, portableExecutableKind, imageFileMachine);
1552 }
1553
1562 void SaveImpl(Stream peStream, Stream pdbStream, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1563 {
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));
1568
1569 SetIsSaved();
1570 PopulatePropertyAndEventTables();
1571
1572 var attributes = asm.GetCustomAttributesData(null);
1573 if (attributes.Count > 0)
1574 {
1575 var mscorlib = ImportAssemblyRef(Universe.CoreLib);
1576 var placeholderTokens = new int[4];
1577 var placeholderTypeNames = new string[] { "AssemblyAttributesGoHere", "AssemblyAttributesGoHereM", "AssemblyAttributesGoHereS", "AssemblyAttributesGoHereSM" };
1578
1579 foreach (var cad in attributes)
1580 {
1581 int index;
1582 if (cad.Constructor.DeclaringType.BaseType == Universe.System_Security_Permissions_CodeAccessSecurityAttribute)
1583 {
1584 if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute)
1585 index = 3;
1586 else
1587 index = 2;
1588 }
1589 else if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute)
1590 {
1591 index = 1;
1592 }
1593 else
1594 {
1595 index = 0;
1596 }
1597
1598 if (placeholderTokens[index] == 0)
1599 {
1600 // we manually add a TypeRef without looking it up in mscorlib, because Mono and Silverlight's mscorlib don't have these types
1601 placeholderTokens[index] = AddTypeRefByName(mscorlib, "System.Runtime.CompilerServices", placeholderTypeNames[index]);
1602 }
1603
1604 SetCustomAttribute(placeholderTokens[index], cad.__ToBuilder());
1605 }
1606 }
1607
1608 FillAssemblyRefTable();
1609 ModuleWriter.WriteModule(null, null, this, PEFileKinds.Dll, portableExecutableKind, imageFileMachine, nativeResources, default, null, peStream, null, pdbStream);
1610 }
1611
1612 public void __AddAssemblyReference(AssemblyName assemblyName)
1613 {
1614 __AddAssemblyReference(assemblyName, null);
1615 }
1616
1617 public void __AddAssemblyReference(AssemblyName assemblyName, Assembly assembly)
1618 {
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);
1624 }
1625
1626 public override AssemblyName[] __GetReferencedAssemblies()
1627 {
1628 var list = new List<AssemblyName>();
1629 if (referencedAssemblyNames != null)
1630 foreach (var name in referencedAssemblyNames)
1631 if (list.Contains(name) == false)
1632 list.Add(name);
1633
1634 foreach (var asm in referencedAssemblies.Keys)
1635 {
1636 var name = asm.GetName();
1637 if (list.Contains(name) == false)
1638 list.Add(name);
1639 }
1640
1641 return list.ToArray();
1642 }
1643
1644 public void __AddModuleReference(string module)
1645 {
1646 ModuleRefTable.FindOrAddRecord(module == null ? default : GetOrAddString(module));
1647 }
1648
1649 public override string[] __GetReferencedModules()
1650 {
1651 var arr = new string[ModuleRefTable.RowCount];
1652 for (int i = 0; i < arr.Length; i++)
1653 arr[i] = GetString(ModuleRefTable.records[i]);
1654
1655 return arr;
1656 }
1657
1658 public override Type[] __GetReferencedTypes()
1659 {
1660 var list = new List<Type>();
1661 foreach (var kv in typeTokens)
1662 if (kv.Value >> 24 == TypeRefTable.Index)
1663 list.Add(kv.Key);
1664
1665 return list.ToArray();
1666 }
1667
1668 public override Type[] __GetExportedTypes()
1669 {
1670 throw new NotImplementedException();
1671 }
1672
1673 public int __AddModule(int flags, string name, byte[] hash)
1674 {
1675 var file = new FileTable.Record();
1676 file.Flags = flags;
1677 file.Name = GetOrAddString(name);
1678 file.HashValue = GetOrAddBlob(hash);
1679 return MetadataTokens.GetToken(MetadataTokens.AssemblyFileHandle(FileTable.AddRecord(file)));
1680 }
1681
1682 public int __AddManifestResource(int offset, ResourceAttributes flags, string name, int implementation)
1683 {
1684 var res = new ManifestResourceTable.Record();
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)));
1690 }
1691
1692 public void __SetCustomAttributeFor(int token, CustomAttributeBuilder customBuilder)
1693 {
1694 SetCustomAttribute(token, customBuilder);
1695 }
1696
1697 internal void SetInterfaceImplementationCustomAttribute(TypeBuilder typeBuilder, Type interfaceType, CustomAttributeBuilder cab)
1698 {
1699 // NOTE since interfaceimpls are extremely common and custom attributes on them are extremely rare,
1700 // we store (and resolve) the custom attributes in such away as to avoid impacting the common case performance
1701 interfaceImplCustomAttributes ??= new List<InterfaceImplCustomAttribute>();
1702
1703 var rec = new InterfaceImplCustomAttribute();
1704 rec.type = typeBuilder.MetadataToken;
1705
1706 var token = GetTypeToken(interfaceType).Token;
1707 token = (token >> 24) switch
1708 {
1709 TypeDefTable.Index => (token & 0xFFFFFF) << 2 | 0,
1710 TypeRefTable.Index => (token & 0xFFFFFF) << 2 | 1,
1711 TypeSpecTable.Index => (token & 0xFFFFFF) << 2 | 2,
1712 _ => throw new InvalidOperationException(),
1713 };
1714
1715 rec.interfaceType = token;
1716 rec.pseudoToken = AllocPseudoToken();
1717 interfaceImplCustomAttributes.Add(rec);
1718
1719 SetCustomAttribute(rec.pseudoToken, cab);
1720 }
1721
1722 internal void ResolveInterfaceImplPseudoTokens()
1723 {
1724 if (interfaceImplCustomAttributes != null)
1725 {
1726 foreach (var rec in interfaceImplCustomAttributes)
1727 {
1728 for (int i = 0; i < InterfaceImplTable.records.Length; i++)
1729 {
1730 if (InterfaceImplTable.records[i].Class == rec.type && InterfaceImplTable.records[i].Interface == rec.interfaceType)
1731 {
1732 RegisterTokenFixup(rec.pseudoToken, MetadataTokens.GetToken(MetadataTokens.InterfaceImplementationHandle(i + 1)));
1733 break;
1734 }
1735 }
1736 }
1737 }
1738 }
1739
1740 internal void FixupPseudoToken(ref int token)
1741 {
1742 if (IsPseudoToken(token))
1743 token = ResolvePseudoToken(token);
1744 }
1745
1746 internal void SetIsSaved()
1747 {
1748 if (saved)
1749 throw new InvalidOperationException();
1750
1751 saved = true;
1752 }
1753
1754 internal bool IsSaved
1755 {
1756 get { return saved; }
1757 }
1758
1759 }
1760
1761}
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
Definition Signature.cs:35
Represents a method signature from IL metadadata.
Implements a ResourceSectionBuilder for writing IKVM reflection resource section data.