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 */
24 using System;
25 using System.Collections.Generic;
26 using System.IO;
27 using System.Diagnostics;
28 #if !NO_SYMBOL_WRITER
29 using System.Diagnostics.SymbolStore;
30 #endif
31 using System.Security.Cryptography;
32 using System.Resources;
33 using System.Runtime.CompilerServices;
34 using System.Runtime.InteropServices;
35 using IKVM.Reflection.Impl;
36 using IKVM.Reflection.Metadata;
37 using IKVM.Reflection.Writer;
38 
39 namespace IKVM.Reflection.Emit
40 {
41 	public sealed class ModuleBuilder : Module, ITypeOwner
42 	{
43 		private static readonly bool usePublicKeyAssemblyReference = false;
44 		private Guid mvid;
45 		private uint timestamp;
46 		private long imageBaseAddress = 0x00400000;
47 		private long stackReserve = -1;
48 		private int fileAlignment = 0x200;
49 		private DllCharacteristics dllCharacteristics = DllCharacteristics.DynamicBase | DllCharacteristics.NoSEH | DllCharacteristics.NXCompat | DllCharacteristics.TerminalServerAware;
50 		private readonly AssemblyBuilder asm;
51 		internal readonly string moduleName;
52 		internal readonly string fileName;
53 		internal readonly ISymbolWriterImpl symbolWriter;
54 		private readonly TypeBuilder moduleType;
55 		private readonly List<TypeBuilder> types = new List<TypeBuilder>();
56 		private readonly Dictionary<Type, int> typeTokens = new Dictionary<Type, int>();
57 		private readonly Dictionary<Type, int> memberRefTypeTokens = new Dictionary<Type, int>();
58 		internal readonly ByteBuffer methodBodies = new ByteBuffer(128 * 1024);
59 		internal readonly List<int> tokenFixupOffsets = new List<int>();
60 		internal readonly ByteBuffer initializedData = new ByteBuffer(512);
61 		internal ResourceSection unmanagedResources;
62 		private readonly Dictionary<MemberRefKey, int> importedMemberRefs = new Dictionary<MemberRefKey, int>();
63 		private readonly Dictionary<MethodSpecKey, int> importedMethodSpecs = new Dictionary<MethodSpecKey, int>();
64 		private readonly Dictionary<Assembly, int> referencedAssemblies = new Dictionary<Assembly, int>();
65 		private List<AssemblyName> referencedAssemblyNames;
66 		private int nextPseudoToken = -1;
67 		private readonly List<int> resolvedTokens = new List<int>();
68 		internal readonly TableHeap Tables = new TableHeap();
69 		internal readonly StringHeap Strings = new StringHeap();
70 		internal readonly UserStringHeap UserStrings = new UserStringHeap();
71 		internal readonly GuidHeap Guids = new GuidHeap();
72 		internal readonly BlobHeap Blobs = new BlobHeap();
73 		internal readonly List<VTableFixups> vtablefixups = new List<VTableFixups>();
74 		internal readonly List<UnmanagedExport> unmanagedExports = new List<UnmanagedExport>();
75 		private List<InterfaceImplCustomAttribute> interfaceImplCustomAttributes;
76 		private readonly List<ResourceWriterRecord> resourceWriters = new List<ResourceWriterRecord>();
77 		private bool saved;
78 
79 		private struct ResourceWriterRecord
80 		{
81 			private readonly string name;
82 #if !CORECLR
83 			private readonly ResourceWriter rw;
84 #endif
85 			private readonly Stream stream;
86 			private readonly ResourceAttributes attributes;
87 
88 #if CORECLR
ResourceWriterRecordIKVM.Reflection.Emit.ModuleBuilder.ResourceWriterRecord89 			internal ResourceWriterRecord(string name, Stream stream, ResourceAttributes attributes)
90 			{
91 				this.name = name;
92 				this.stream = stream;
93 				this.attributes = attributes;
94 			}
95 #else
ResourceWriterRecordIKVM.Reflection.Emit.ModuleBuilder.ResourceWriterRecord96 			internal ResourceWriterRecord(string name, Stream stream, ResourceAttributes attributes)
97 				: this(name, null, stream, attributes)
98 			{
99 			}
100 
ResourceWriterRecordIKVM.Reflection.Emit.ModuleBuilder.ResourceWriterRecord101 			internal ResourceWriterRecord(string name, ResourceWriter rw, Stream stream, ResourceAttributes attributes)
102 			{
103 				this.name = name;
104 				this.rw = rw;
105 				this.stream = stream;
106 				this.attributes = attributes;
107 			}
108 #endif
109 
EmitIKVM.Reflection.Emit.ModuleBuilder.ResourceWriterRecord110 			internal void Emit(ModuleBuilder mb, int offset)
111 			{
112 #if !CORECLR
113 				if (rw != null)
114 				{
115 					rw.Generate();
116 				}
117 #endif
118 				ManifestResourceTable.Record rec = new ManifestResourceTable.Record();
119 				rec.Offset = offset;
120 				rec.Flags = (int)attributes;
121 				rec.Name = mb.Strings.Add(name);
122 				rec.Implementation = 0;
123 				mb.ManifestResource.AddRecord(rec);
124 			}
125 
GetLengthIKVM.Reflection.Emit.ModuleBuilder.ResourceWriterRecord126 			internal int GetLength()
127 			{
128 				return 4 + (int)stream.Length;
129 			}
130 
WriteIKVM.Reflection.Emit.ModuleBuilder.ResourceWriterRecord131 			internal void Write(MetadataWriter mw)
132 			{
133 				mw.Write((int)stream.Length);
134 				stream.Position = 0;
135 				byte[] buffer = new byte[8192];
136 				int length;
137 				while ((length = stream.Read(buffer, 0, buffer.Length)) != 0)
138 				{
139 					mw.Write(buffer, 0, length);
140 				}
141 			}
142 
CloseIKVM.Reflection.Emit.ModuleBuilder.ResourceWriterRecord143 			internal void Close()
144 			{
145 #if !CORECLR
146 				if (rw != null)
147 				{
148 					rw.Close();
149 				}
150 #endif
151 			}
152 		}
153 
154 		internal struct VTableFixups
155 		{
156 			internal uint initializedDataOffset;
157 			internal ushort count;
158 			internal ushort type;
159 
160 			internal int SlotWidth
161 			{
162 				get { return (type & 0x02) == 0 ? 4 : 8; }
163 			}
164 		}
165 
166 		struct InterfaceImplCustomAttribute
167 		{
168 			internal int type;
169 			internal int interfaceType;
170 			internal int pseudoToken;
171 		}
172 
173 		struct MemberRefKey : IEquatable<MemberRefKey>
174 		{
175 			private readonly Type type;
176 			private readonly string name;
177 			private readonly Signature signature;
178 
MemberRefKeyIKVM.Reflection.Emit.ModuleBuilder.MemberRefKey179 			internal MemberRefKey(Type type, string name, Signature signature)
180 			{
181 				this.type = type;
182 				this.name = name;
183 				this.signature = signature;
184 			}
185 
EqualsIKVM.Reflection.Emit.ModuleBuilder.MemberRefKey186 			public bool Equals(MemberRefKey other)
187 			{
188 				return other.type.Equals(type)
189 					&& other.name == name
190 					&& other.signature.Equals(signature);
191 			}
192 
EqualsIKVM.Reflection.Emit.ModuleBuilder.MemberRefKey193 			public override bool Equals(object obj)
194 			{
195 				MemberRefKey? other = obj as MemberRefKey?;
196 				return other != null && Equals(other.Value);
197 			}
198 
GetHashCodeIKVM.Reflection.Emit.ModuleBuilder.MemberRefKey199 			public override int GetHashCode()
200 			{
201 				return type.GetHashCode() + name.GetHashCode() + signature.GetHashCode();
202 			}
203 
LookupMethodIKVM.Reflection.Emit.ModuleBuilder.MemberRefKey204 			internal MethodBase LookupMethod()
205 			{
206 				return type.FindMethod(name, (MethodSignature)signature);
207 			}
208 		}
209 
210 		struct MethodSpecKey : IEquatable<MethodSpecKey>
211 		{
212 			private readonly Type type;
213 			private readonly string name;
214 			private readonly MethodSignature signature;
215 			private readonly Type[] genericParameters;
216 
MethodSpecKeyIKVM.Reflection.Emit.ModuleBuilder.MethodSpecKey217 			internal MethodSpecKey(Type type, string name, MethodSignature signature, Type[] genericParameters)
218 			{
219 				this.type = type;
220 				this.name = name;
221 				this.signature = signature;
222 				this.genericParameters = genericParameters;
223 			}
224 
EqualsIKVM.Reflection.Emit.ModuleBuilder.MethodSpecKey225 			public bool Equals(MethodSpecKey other)
226 			{
227 				return other.type.Equals(type)
228 					&& other.name == name
229 					&& other.signature.Equals(signature)
230 					&& Util.ArrayEquals(other.genericParameters, genericParameters);
231 			}
232 
EqualsIKVM.Reflection.Emit.ModuleBuilder.MethodSpecKey233 			public override bool Equals(object obj)
234 			{
235 				MethodSpecKey? other = obj as MethodSpecKey?;
236 				return other != null && Equals(other.Value);
237 			}
238 
GetHashCodeIKVM.Reflection.Emit.ModuleBuilder.MethodSpecKey239 			public override int GetHashCode()
240 			{
241 				return type.GetHashCode() + name.GetHashCode() + signature.GetHashCode() + Util.GetHashCode(genericParameters);
242 			}
243 		}
244 
ModuleBuilder(AssemblyBuilder asm, string moduleName, string fileName, bool emitSymbolInfo)245 		internal ModuleBuilder(AssemblyBuilder asm, string moduleName, string fileName, bool emitSymbolInfo)
246 			: base(asm.universe)
247 		{
248 			this.asm = asm;
249 			this.moduleName = moduleName;
250 			this.fileName = fileName;
251 			if (emitSymbolInfo)
252 			{
253 				symbolWriter = SymbolSupport.CreateSymbolWriterFor(this);
254 				if (universe.Deterministic && !symbolWriter.IsDeterministic)
255 				{
256 					throw new NotSupportedException();
257 				}
258 			}
259 			if (!universe.Deterministic)
260 			{
261 				__PEHeaderTimeDateStamp = DateTime.UtcNow;
262 				mvid = Guid.NewGuid();
263 			}
264 			// <Module> must be the first record in the TypeDef table
265 			moduleType = new TypeBuilder(this, null, "<Module>");
266 			types.Add(moduleType);
267 		}
268 
PopulatePropertyAndEventTables()269 		internal void PopulatePropertyAndEventTables()
270 		{
271 			// LAMESPEC the PropertyMap and EventMap tables are not required to be sorted by the CLI spec,
272 			// but .NET sorts them and Mono requires them to be sorted, so we have to populate the
273 			// tables in the right order
274 			foreach (TypeBuilder type in types)
275 			{
276 				type.PopulatePropertyAndEventTables();
277 			}
278 		}
279 
WriteTypeDefTable(MetadataWriter mw)280 		internal void WriteTypeDefTable(MetadataWriter mw)
281 		{
282 			int fieldList = 1;
283 			int methodList = 1;
284 			foreach (TypeBuilder type in types)
285 			{
286 				type.WriteTypeDefRecord(mw, ref fieldList, ref methodList);
287 			}
288 		}
289 
WriteMethodDefTable(int baseRVA, MetadataWriter mw)290 		internal void WriteMethodDefTable(int baseRVA, MetadataWriter mw)
291 		{
292 			int paramList = 1;
293 			foreach (TypeBuilder type in types)
294 			{
295 				type.WriteMethodDefRecords(baseRVA, mw, ref paramList);
296 			}
297 		}
298 
WriteParamTable(MetadataWriter mw)299 		internal void WriteParamTable(MetadataWriter mw)
300 		{
301 			foreach (TypeBuilder type in types)
302 			{
303 				type.WriteParamRecords(mw);
304 			}
305 		}
306 
WriteFieldTable(MetadataWriter mw)307 		internal void WriteFieldTable(MetadataWriter mw)
308 		{
309 			foreach (TypeBuilder type in types)
310 			{
311 				type.WriteFieldRecords(mw);
312 			}
313 		}
314 
AllocPseudoToken()315 		internal int AllocPseudoToken()
316 		{
317 			return nextPseudoToken--;
318 		}
319 
DefineType(string name)320 		public TypeBuilder DefineType(string name)
321 		{
322 			return DefineType(name, TypeAttributes.Class);
323 		}
324 
DefineType(string name, TypeAttributes attr)325 		public TypeBuilder DefineType(string name, TypeAttributes attr)
326 		{
327 			return DefineType(name, attr, null);
328 		}
329 
DefineType(string name, TypeAttributes attr, Type parent)330 		public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent)
331 		{
332 			return DefineType(name, attr, parent, PackingSize.Unspecified, 0);
333 		}
334 
DefineType(string name, TypeAttributes attr, Type parent, int typesize)335 		public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, int typesize)
336 		{
337 			return DefineType(name, attr, parent, PackingSize.Unspecified, typesize);
338 		}
339 
DefineType(string name, TypeAttributes attr, Type parent, PackingSize packsize)340 		public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packsize)
341 		{
342 			return DefineType(name, attr, parent, packsize, 0);
343 		}
344 
DefineType(string name, TypeAttributes attr, Type parent, Type[] interfaces)345 		public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, Type[] interfaces)
346 		{
347 			TypeBuilder tb = DefineType(name, attr, parent);
348 			foreach (Type iface in interfaces)
349 			{
350 				tb.AddInterfaceImplementation(iface);
351 			}
352 			return tb;
353 		}
354 
DefineType(string name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize)355 		public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize)
356 		{
357 			string ns = null;
358 			int lastdot = name.LastIndexOf('.');
359 			if (lastdot > 0)
360 			{
361 				ns = name.Substring(0, lastdot);
362 				name = name.Substring(lastdot + 1);
363 			}
364 			TypeBuilder typeBuilder = __DefineType(ns, name);
365 			typeBuilder.__SetAttributes(attr);
366 			typeBuilder.SetParent(parent);
367 			if (packingSize != PackingSize.Unspecified || typesize != 0)
368 			{
369 				typeBuilder.__SetLayout((int)packingSize, typesize);
370 			}
371 			return typeBuilder;
372 		}
373 
__DefineType(string ns, string name)374 		public TypeBuilder __DefineType(string ns, string name)
375 		{
376 			return DefineType(this, ns, name);
377 		}
378 
DefineType(ITypeOwner owner, string ns, string name)379 		internal TypeBuilder DefineType(ITypeOwner owner, string ns, string name)
380 		{
381 			TypeBuilder typeBuilder = new TypeBuilder(owner, ns, name);
382 			types.Add(typeBuilder);
383 			return typeBuilder;
384 		}
385 
DefineEnum(string name, TypeAttributes visibility, Type underlyingType)386 		public EnumBuilder DefineEnum(string name, TypeAttributes visibility, Type underlyingType)
387 		{
388 			TypeBuilder tb = DefineType(name, (visibility & TypeAttributes.VisibilityMask) | TypeAttributes.Sealed, universe.System_Enum);
389 			FieldBuilder fb = tb.DefineField("value__", underlyingType, FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
390 			return new EnumBuilder(tb, fb);
391 		}
392 
__DefineField(string name, Type type, CustomModifiers customModifiers, FieldAttributes attributes)393 		public FieldBuilder __DefineField(string name, Type type, CustomModifiers customModifiers, FieldAttributes attributes)
394 		{
395 			return moduleType.__DefineField(name, type, customModifiers, attributes);
396 		}
397 
398 		[Obsolete("Please use __DefineField(string, Type, CustomModifiers, FieldAttributes) instead.")]
__DefineField(string name, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes)399 		public FieldBuilder __DefineField(string name, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes)
400 		{
401 			return moduleType.DefineField(name, type, requiredCustomModifiers, optionalCustomModifiers, attributes);
402 		}
403 
__DefineModuleInitializer(MethodAttributes visibility)404 		public ConstructorBuilder __DefineModuleInitializer(MethodAttributes visibility)
405 		{
406 			return moduleType.DefineConstructor(visibility | MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, Type.EmptyTypes);
407 		}
408 
DefineUninitializedData(string name, int size, FieldAttributes attributes)409 		public FieldBuilder DefineUninitializedData(string name, int size, FieldAttributes attributes)
410 		{
411 			return moduleType.DefineUninitializedData(name, size, attributes);
412 		}
413 
DefineInitializedData(string name, byte[] data, FieldAttributes attributes)414 		public FieldBuilder DefineInitializedData(string name, byte[] data, FieldAttributes attributes)
415 		{
416 			return moduleType.DefineInitializedData(name, data, attributes);
417 		}
418 
DefineGlobalMethod(string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)419 		public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)
420 		{
421 			return moduleType.DefineMethod(name, attributes, returnType, parameterTypes);
422 		}
423 
DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)424 		public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
425 		{
426 			return moduleType.DefineMethod(name, attributes, callingConvention, returnType, parameterTypes);
427 		}
428 
DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)429 		public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
430 		{
431 			return moduleType.DefineMethod(name, attributes, callingConvention, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
432 		}
433 
DefinePInvokeMethod(string name, string dllName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)434 		public MethodBuilder DefinePInvokeMethod(string name, string dllName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
435 		{
436 			return moduleType.DefinePInvokeMethod(name, dllName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
437 		}
438 
DefinePInvokeMethod(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)439 		public MethodBuilder DefinePInvokeMethod(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
440 		{
441 			return moduleType.DefinePInvokeMethod(name, dllName, entryName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
442 		}
443 
CreateGlobalFunctions()444 		public void CreateGlobalFunctions()
445 		{
446 			moduleType.CreateType();
447 		}
448 
AddTypeForwarder(Type type, bool includeNested)449 		internal void AddTypeForwarder(Type type, bool includeNested)
450 		{
451 			ExportType(type);
452 			if (includeNested && !type.__IsMissing)
453 			{
454 				foreach (Type nested in type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic))
455 				{
456 					// we export all nested types (i.e. even the private ones)
457 					// (this behavior is the same as the C# compiler)
458 					AddTypeForwarder(nested, true);
459 				}
460 			}
461 		}
462 
ExportType(Type type)463 		private int ExportType(Type type)
464 		{
465 			ExportedTypeTable.Record rec = new ExportedTypeTable.Record();
466 			if (asm.ImageRuntimeVersion == "v2.0.50727")
467 			{
468 				// 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)
469 				rec.TypeDefId = type.MetadataToken;
470 			}
471 			SetTypeNameAndTypeNamespace(type.TypeName, out rec.TypeName, out rec.TypeNamespace);
472 			if (type.IsNested)
473 			{
474 				rec.Flags = 0;
475 				rec.Implementation = ExportType(type.DeclaringType);
476 			}
477 			else
478 			{
479 				rec.Flags = 0x00200000;	// CorTypeAttr.tdForwarder
480 				rec.Implementation = ImportAssemblyRef(type.Assembly);
481 			}
482 			return 0x27000000 | this.ExportedType.FindOrAddRecord(rec);
483 		}
484 
SetTypeNameAndTypeNamespace(TypeName name, out int typeName, out int typeNamespace)485 		private void SetTypeNameAndTypeNamespace(TypeName name, out int typeName, out int typeNamespace)
486 		{
487 			typeName = this.Strings.Add(name.Name);
488 			typeNamespace = name.Namespace == null ? 0 : this.Strings.Add(name.Namespace);
489 		}
490 
SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)491 		public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
492 		{
493 			SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
494 		}
495 
SetCustomAttribute(CustomAttributeBuilder customBuilder)496 		public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
497 		{
498 			SetCustomAttribute(0x00000001, customBuilder);
499 		}
500 
SetCustomAttribute(int token, CustomAttributeBuilder customBuilder)501 		internal void SetCustomAttribute(int token, CustomAttributeBuilder customBuilder)
502 		{
503 			CustomAttributeTable.Record rec = new CustomAttributeTable.Record();
504 			rec.Parent = token;
505 			rec.Type = asm.IsWindowsRuntime ? customBuilder.Constructor.ImportTo(this) : GetConstructorToken(customBuilder.Constructor).Token;
506 			rec.Value = customBuilder.WriteBlob(this);
507 			this.CustomAttribute.AddRecord(rec);
508 		}
509 
AddDeclSecurityRecord(int token, int action, int blob)510 		private void AddDeclSecurityRecord(int token, int action, int blob)
511 		{
512 			DeclSecurityTable.Record rec = new DeclSecurityTable.Record();
513 			rec.Action = (short)action;
514 			rec.Parent = token;
515 			rec.PermissionSet = blob;
516 			this.DeclSecurity.AddRecord(rec);
517 		}
518 
519 #if !CORECLR
AddDeclarativeSecurity(int token, System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet)520 		internal void AddDeclarativeSecurity(int token, System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet)
521 		{
522 			// like Ref.Emit, we're using the .NET 1.x xml format
523 			AddDeclSecurityRecord(token, (int)securityAction, this.Blobs.Add(ByteBuffer.Wrap(System.Text.Encoding.Unicode.GetBytes(permissionSet.ToXml().ToString()))));
524 		}
525 #endif
526 
AddDeclarativeSecurity(int token, List<CustomAttributeBuilder> declarativeSecurity)527 		internal void AddDeclarativeSecurity(int token, List<CustomAttributeBuilder> declarativeSecurity)
528 		{
529 			Dictionary<int, List<CustomAttributeBuilder>> ordered = new Dictionary<int, List<CustomAttributeBuilder>>();
530 			foreach (CustomAttributeBuilder cab in declarativeSecurity)
531 			{
532 				int action;
533 				// check for HostProtectionAttribute without SecurityAction
534 				if (cab.ConstructorArgumentCount == 0)
535 				{
536 					action = (int)System.Security.Permissions.SecurityAction.LinkDemand;
537 				}
538 				else
539 				{
540 					action = (int)cab.GetConstructorArgument(0);
541 				}
542 				if (cab.IsLegacyDeclSecurity)
543 				{
544 					AddDeclSecurityRecord(token, action, cab.WriteLegacyDeclSecurityBlob(this));
545 					continue;
546 				}
547 				List<CustomAttributeBuilder> list;
548 				if (!ordered.TryGetValue(action, out list))
549 				{
550 					list = new List<CustomAttributeBuilder>();
551 					ordered.Add(action, list);
552 				}
553 				list.Add(cab);
554 			}
555 			foreach (KeyValuePair<int, List<CustomAttributeBuilder>> kv in ordered)
556 			{
557 				AddDeclSecurityRecord(token, kv.Key, WriteDeclSecurityBlob(kv.Value));
558 			}
559 		}
560 
WriteDeclSecurityBlob(List<CustomAttributeBuilder> list)561 		private int WriteDeclSecurityBlob(List<CustomAttributeBuilder> list)
562 		{
563 			ByteBuffer namedArgs = new ByteBuffer(100);
564 			ByteBuffer bb = new ByteBuffer(list.Count * 100);
565 			bb.Write((byte)'.');
566 			bb.WriteCompressedUInt(list.Count);
567 			foreach (CustomAttributeBuilder cab in list)
568 			{
569 				bb.Write(cab.Constructor.DeclaringType.AssemblyQualifiedName);
570 				namedArgs.Clear();
571 				cab.WriteNamedArgumentsForDeclSecurity(this, namedArgs);
572 				bb.WriteCompressedUInt(namedArgs.Length);
573 				bb.Write(namedArgs);
574 			}
575 			return this.Blobs.Add(bb);
576 		}
577 
DefineManifestResource(string name, Stream stream, ResourceAttributes attribute)578 		public void DefineManifestResource(string name, Stream stream, ResourceAttributes attribute)
579 		{
580 			resourceWriters.Add(new ResourceWriterRecord(name, stream, attribute));
581 		}
582 
583 #if !CORECLR
DefineResource(string name, string description)584 		public IResourceWriter DefineResource(string name, string description)
585 		{
586 			return DefineResource(name, description, ResourceAttributes.Public);
587 		}
588 
DefineResource(string name, string description, ResourceAttributes attribute)589 		public IResourceWriter DefineResource(string name, string description, ResourceAttributes attribute)
590 		{
591 			// FXBUG we ignore the description, because there is no such thing
592 
593 			MemoryStream mem = new MemoryStream();
594 			ResourceWriter rw = new ResourceWriter(mem);
595 			resourceWriters.Add(new ResourceWriterRecord(name, rw, mem, attribute));
596 			return rw;
597 		}
598 #endif
599 
EmitResources()600 		internal void EmitResources()
601 		{
602 			int offset = 0;
603 			foreach (ResourceWriterRecord rwr in resourceWriters)
604 			{
605 				// resources must be 8-byte aligned
606 				offset = (offset + 7) & ~7;
607 				rwr.Emit(this, offset);
608 				offset += rwr.GetLength();
609 			}
610 		}
611 
WriteResources(MetadataWriter mw)612 		internal void WriteResources(MetadataWriter mw)
613 		{
614 			int offset = 0;
615 			foreach (ResourceWriterRecord rwr in resourceWriters)
616 			{
617 				// resources must be 8-byte aligned
618 				int alignment = ((offset + 7) & ~7) - offset;
619 				for (int i = 0; i < alignment; i++)
620 				{
621 					mw.Write((byte)0);
622 				}
623 				rwr.Write(mw);
624 				offset += rwr.GetLength() + alignment;
625 			}
626 		}
627 
CloseResources()628 		internal void CloseResources()
629 		{
630 			foreach (ResourceWriterRecord rwr in resourceWriters)
631 			{
632 				rwr.Close();
633 			}
634 		}
635 
GetManifestResourcesLength()636 		internal int GetManifestResourcesLength()
637 		{
638 			int length = 0;
639 			foreach (ResourceWriterRecord rwr in resourceWriters)
640 			{
641 				// resources must be 8-byte aligned
642 				length = (length + 7) & ~7;
643 				length += rwr.GetLength();
644 			}
645 			return length;
646 		}
647 
648 		public override Assembly Assembly
649 		{
650 			get { return asm; }
651 		}
652 
FindType(TypeName name)653 		internal override Type FindType(TypeName name)
654 		{
655 			foreach (Type type in types)
656 			{
657 				if (type.TypeName == name)
658 				{
659 					return type;
660 				}
661 			}
662 			return null;
663 		}
664 
FindTypeIgnoreCase(TypeName lowerCaseName)665 		internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
666 		{
667 			foreach (Type type in types)
668 			{
669 				if (type.TypeName.ToLowerInvariant() == lowerCaseName)
670 				{
671 					return type;
672 				}
673 			}
674 			return null;
675 		}
676 
GetTypesImpl(List<Type> list)677 		internal override void GetTypesImpl(List<Type> list)
678 		{
679 			foreach (Type type in types)
680 			{
681 				if (type != moduleType)
682 				{
683 					list.Add(type);
684 				}
685 			}
686 		}
687 
688 #if !NO_SYMBOL_WRITER
DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType)689 		public ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType)
690 		{
691 			return symbolWriter.DefineDocument(url, language, languageVendor, documentType);
692 		}
693 #endif
694 
__GetAssemblyToken(Assembly assembly)695 		public int __GetAssemblyToken(Assembly assembly)
696 		{
697 			return ImportAssemblyRef(assembly);
698 		}
699 
GetTypeToken(string name)700 		public TypeToken GetTypeToken(string name)
701 		{
702 			return new TypeToken(GetType(name, true, false).MetadataToken);
703 		}
704 
GetTypeToken(Type type)705 		public TypeToken GetTypeToken(Type type)
706 		{
707 			if (type.Module == this && !asm.IsWindowsRuntime)
708 			{
709 				return new TypeToken(type.GetModuleBuilderToken());
710 			}
711 			else
712 			{
713 				return new TypeToken(ImportType(type));
714 			}
715 		}
716 
GetTypeTokenForMemberRef(Type type)717 		internal int GetTypeTokenForMemberRef(Type type)
718 		{
719 			if (type.__IsMissing)
720 			{
721 				return ImportType(type);
722 			}
723 			else if (type.IsGenericTypeDefinition)
724 			{
725 				int token;
726 				if (!memberRefTypeTokens.TryGetValue(type, out token))
727 				{
728 					ByteBuffer spec = new ByteBuffer(5);
729 					Signature.WriteTypeSpec(this, spec, type);
730 					token = 0x1B000000 | this.TypeSpec.AddRecord(this.Blobs.Add(spec));
731 					memberRefTypeTokens.Add(type, token);
732 				}
733 				return token;
734 			}
735 			else if (type.IsModulePseudoType)
736 			{
737 				return 0x1A000000 | this.ModuleRef.FindOrAddRecord(this.Strings.Add(type.Module.ScopeName));
738 			}
739 			else
740 			{
741 				return GetTypeToken(type).Token;
742 			}
743 		}
744 
IsFromGenericTypeDefinition(MemberInfo member)745 		private static bool IsFromGenericTypeDefinition(MemberInfo member)
746 		{
747 			Type decl = member.DeclaringType;
748 			return decl != null && !decl.__IsMissing && decl.IsGenericTypeDefinition;
749 		}
750 
GetFieldToken(FieldInfo field)751 		public FieldToken GetFieldToken(FieldInfo field)
752 		{
753 			// NOTE for some reason, when TypeBuilder.GetFieldToken() is used on a field in a generic type definition,
754 			// a memberref token is returned (confirmed on .NET) unlike for Get(Method|Constructor)Token which always
755 			// simply returns the MethodDef token (if the method is from the same module).
756 			FieldBuilder fb = field as FieldBuilder;
757 			if (fb != null && fb.Module == this && !IsFromGenericTypeDefinition(fb))
758 			{
759 				return new FieldToken(fb.MetadataToken);
760 			}
761 			else
762 			{
763 				return new FieldToken(field.ImportTo(this));
764 			}
765 		}
766 
GetMethodToken(MethodInfo method)767 		public MethodToken GetMethodToken(MethodInfo method)
768 		{
769 			MethodBuilder mb = method as MethodBuilder;
770 			if (mb != null && mb.ModuleBuilder == this)
771 			{
772 				return new MethodToken(mb.MetadataToken);
773 			}
774 			else
775 			{
776 				return new MethodToken(method.ImportTo(this));
777 			}
778 		}
779 
780 		// new in .NET 4.5
GetMethodToken(MethodInfo method, IEnumerable<Type> optionalParameterTypes)781 		public MethodToken GetMethodToken(MethodInfo method, IEnumerable<Type> optionalParameterTypes)
782 		{
783 			return __GetMethodToken(method, Util.ToArray(optionalParameterTypes), null);
784 		}
785 
__GetMethodToken(MethodInfo method, Type[] optionalParameterTypes, CustomModifiers[] customModifiers)786 		public MethodToken __GetMethodToken(MethodInfo method, Type[] optionalParameterTypes, CustomModifiers[] customModifiers)
787 		{
788 			ByteBuffer sig = new ByteBuffer(16);
789 			method.MethodSignature.WriteMethodRefSig(this, sig, optionalParameterTypes, customModifiers);
790 			MemberRefTable.Record record = new MemberRefTable.Record();
791 			if (method.Module == this)
792 			{
793 				record.Class = method.MetadataToken;
794 			}
795 			else
796 			{
797 				record.Class = GetTypeTokenForMemberRef(method.DeclaringType ?? method.Module.GetModuleType());
798 			}
799 			record.Name = Strings.Add(method.Name);
800 			record.Signature = Blobs.Add(sig);
801 			return new MethodToken(0x0A000000 | MemberRef.FindOrAddRecord(record));
802 		}
803 
804 		// when we refer to a method on a generic type definition in the IL stream,
805 		// we need to use a MemberRef (even if the method is in the same module)
GetMethodTokenForIL(MethodInfo method)806 		internal MethodToken GetMethodTokenForIL(MethodInfo method)
807 		{
808 			if (method.IsGenericMethodDefinition)
809 			{
810 				method = method.MakeGenericMethod(method.GetGenericArguments());
811 			}
812 			if (IsFromGenericTypeDefinition(method))
813 			{
814 				return new MethodToken(method.ImportTo(this));
815 			}
816 			else
817 			{
818 				return GetMethodToken(method);
819 			}
820 		}
821 
GetMethodTokenWinRT(MethodInfo method)822 		internal int GetMethodTokenWinRT(MethodInfo method)
823 		{
824 			return asm.IsWindowsRuntime ? method.ImportTo(this) : GetMethodToken(method).Token;
825 		}
826 
GetConstructorToken(ConstructorInfo constructor)827 		public MethodToken GetConstructorToken(ConstructorInfo constructor)
828 		{
829 			return GetMethodToken(constructor.GetMethodInfo());
830 		}
831 
832 		// new in .NET 4.5
GetConstructorToken(ConstructorInfo constructor, IEnumerable<Type> optionalParameterTypes)833 		public MethodToken GetConstructorToken(ConstructorInfo constructor, IEnumerable<Type> optionalParameterTypes)
834 		{
835 			return GetMethodToken(constructor.GetMethodInfo(), optionalParameterTypes);
836 		}
837 
__GetConstructorToken(ConstructorInfo constructor, Type[] optionalParameterTypes, CustomModifiers[] customModifiers)838 		public MethodToken __GetConstructorToken(ConstructorInfo constructor, Type[] optionalParameterTypes, CustomModifiers[] customModifiers)
839 		{
840 			return __GetMethodToken(constructor.GetMethodInfo(), optionalParameterTypes, customModifiers);
841 		}
842 
ImportMethodOrField(Type declaringType, string name, Signature sig)843 		internal int ImportMethodOrField(Type declaringType, string name, Signature sig)
844 		{
845 			int token;
846 			MemberRefKey key = new MemberRefKey(declaringType, name, sig);
847 			if (!importedMemberRefs.TryGetValue(key, out token))
848 			{
849 				MemberRefTable.Record rec = new MemberRefTable.Record();
850 				rec.Class = GetTypeTokenForMemberRef(declaringType);
851 				rec.Name = this.Strings.Add(name);
852 				ByteBuffer bb = new ByteBuffer(16);
853 				sig.WriteSig(this, bb);
854 				rec.Signature = this.Blobs.Add(bb);
855 				token = 0x0A000000 | this.MemberRef.AddRecord(rec);
856 				importedMemberRefs.Add(key, token);
857 			}
858 			return token;
859 		}
860 
ImportMethodSpec(Type declaringType, MethodInfo method, Type[] genericParameters)861 		internal int ImportMethodSpec(Type declaringType, MethodInfo method, Type[] genericParameters)
862 		{
863 			Debug.Assert(method.__IsMissing || method.GetMethodOnTypeDefinition() == method);
864 			int token;
865 			MethodSpecKey key = new MethodSpecKey(declaringType, method.Name, method.MethodSignature, genericParameters);
866 			if (!importedMethodSpecs.TryGetValue(key, out token))
867 			{
868 				MethodSpecTable.Record rec = new MethodSpecTable.Record();
869 				MethodBuilder mb = method as MethodBuilder;
870 				if (mb != null && mb.ModuleBuilder == this && !declaringType.IsGenericType)
871 				{
872 					rec.Method = mb.MetadataToken;
873 				}
874 				else
875 				{
876 					// we're calling ImportMethodOrField directly here, because 'method' may be a MethodDef on a generic TypeDef and 'declaringType' the type instance
877 					// (in order words the method and type have already been decoupled by the caller)
878 					rec.Method = ImportMethodOrField(declaringType, method.Name, method.MethodSignature);
879 				}
880 				Writer.ByteBuffer spec = new Writer.ByteBuffer(10);
881 				Signature.WriteMethodSpec(this, spec, genericParameters);
882 				rec.Instantiation = this.Blobs.Add(spec);
883 				token = 0x2B000000 | this.MethodSpec.FindOrAddRecord(rec);
884 				importedMethodSpecs.Add(key, token);
885 			}
886 			return token;
887 		}
888 
ImportType(Type type)889 		internal int ImportType(Type type)
890 		{
891 			int token;
892 			if (!typeTokens.TryGetValue(type, out token))
893 			{
894 				if (type.HasElementType || type.IsConstructedGenericType || type.__IsFunctionPointer)
895 				{
896 					ByteBuffer spec = new ByteBuffer(5);
897 					Signature.WriteTypeSpec(this, spec, type);
898 					token = 0x1B000000 | this.TypeSpec.AddRecord(this.Blobs.Add(spec));
899 				}
900 				else
901 				{
902 					TypeRefTable.Record rec = new TypeRefTable.Record();
903 					if (type.IsNested)
904 					{
905 						rec.ResolutionScope = GetTypeToken(type.DeclaringType).Token;
906 					}
907 					else if (type.Module == this)
908 					{
909 						rec.ResolutionScope = 1;
910 					}
911 					else
912 					{
913 						rec.ResolutionScope = ImportAssemblyRef(type.Assembly);
914 					}
915 					SetTypeNameAndTypeNamespace(type.TypeName, out rec.TypeName, out rec.TypeNamespace);
916 					token = 0x01000000 | this.TypeRef.AddRecord(rec);
917 				}
918 				typeTokens.Add(type, token);
919 			}
920 			return token;
921 		}
922 
ImportAssemblyRef(Assembly asm)923 		private int ImportAssemblyRef(Assembly asm)
924 		{
925 			int token;
926 			if (!referencedAssemblies.TryGetValue(asm, out token))
927 			{
928 				// We can't write the AssemblyRef record here yet, because the identity of the assembly can still change
929 				// (if it's an AssemblyBuilder).
930 				token = AllocPseudoToken();
931 				referencedAssemblies.Add(asm, token);
932 			}
933 			return token;
934 		}
935 
FillAssemblyRefTable()936 		internal void FillAssemblyRefTable()
937 		{
938 			foreach (KeyValuePair<Assembly, int> kv in referencedAssemblies)
939 			{
940 				if (IsPseudoToken(kv.Value))
941 				{
942 					RegisterTokenFixup(kv.Value, FindOrAddAssemblyRef(kv.Key.GetName(), false));
943 				}
944 			}
945 		}
946 
FindOrAddAssemblyRef(AssemblyName name, bool alwaysAdd)947 		private int FindOrAddAssemblyRef(AssemblyName name, bool alwaysAdd)
948 		{
949 			AssemblyRefTable.Record rec = new AssemblyRefTable.Record();
950 			Version ver = name.Version ?? new Version(0, 0, 0, 0);
951 			rec.MajorVersion = (ushort)ver.Major;
952 			rec.MinorVersion = (ushort)ver.Minor;
953 			rec.BuildNumber = (ushort)ver.Build;
954 			rec.RevisionNumber = (ushort)ver.Revision;
955 			rec.Flags = (int)(name.Flags & ~AssemblyNameFlags.PublicKey);
956 			const AssemblyNameFlags afPA_Specified = (AssemblyNameFlags)0x0080;
957 			const AssemblyNameFlags afPA_Mask = (AssemblyNameFlags)0x0070;
958 			if ((name.RawFlags & afPA_Specified) != 0)
959 			{
960 				rec.Flags |= (int)(name.RawFlags & afPA_Mask);
961 			}
962 			if (name.ContentType == AssemblyContentType.WindowsRuntime)
963 			{
964 				rec.Flags |= 0x0200;
965 			}
966 			byte[] publicKeyOrToken = null;
967 			if (usePublicKeyAssemblyReference)
968 			{
969 				publicKeyOrToken = name.GetPublicKey();
970 			}
971 			if (publicKeyOrToken == null || publicKeyOrToken.Length == 0)
972 			{
973 				publicKeyOrToken = name.GetPublicKeyToken() ?? Empty<byte>.Array;
974 			}
975 			else
976 			{
977 				const int PublicKey = 0x0001;
978 				rec.Flags |= PublicKey;
979 			}
980 			rec.PublicKeyOrToken = this.Blobs.Add(ByteBuffer.Wrap(publicKeyOrToken));
981 			rec.Name = this.Strings.Add(name.Name);
982 			rec.Culture = name.Culture == null ? 0 : this.Strings.Add(name.Culture);
983 			if (name.hash != null)
984 			{
985 				rec.HashValue = this.Blobs.Add(ByteBuffer.Wrap(name.hash));
986 			}
987 			else
988 			{
989 				rec.HashValue = 0;
990 			}
991 			return 0x23000000 | (alwaysAdd ? this.AssemblyRef.AddRecord(rec) : this.AssemblyRef.FindOrAddRecord(rec));
992 		}
993 
WriteSymbolTokenMap()994 		internal void WriteSymbolTokenMap()
995 		{
996 			for (int i = 0; i < resolvedTokens.Count; i++)
997 			{
998 				int newToken = resolvedTokens[i];
999 				// The symbol API doesn't support remapping arbitrary integers, the types have to be the same,
1000 				// so we copy the type from the newToken, because our pseudo tokens don't have a type.
1001 				// (see MethodToken.SymbolToken)
1002 				int oldToken = (i + 1) | (newToken & ~0xFFFFFF);
1003 				SymbolSupport.RemapToken(symbolWriter, oldToken, newToken);
1004 			}
1005 		}
1006 
RegisterTokenFixup(int pseudoToken, int realToken)1007 		internal void RegisterTokenFixup(int pseudoToken, int realToken)
1008 		{
1009 			int index = -(pseudoToken + 1);
1010 			while (resolvedTokens.Count <= index)
1011 			{
1012 				resolvedTokens.Add(0);
1013 			}
1014 			resolvedTokens[index] = realToken;
1015 		}
1016 
IsPseudoToken(int token)1017 		internal static bool IsPseudoToken(int token)
1018 		{
1019 			return token < 0;
1020 		}
1021 
ResolvePseudoToken(int pseudoToken)1022 		internal int ResolvePseudoToken(int pseudoToken)
1023 		{
1024 			int index = -(pseudoToken + 1);
1025 			return resolvedTokens[index];
1026 		}
1027 
ApplyUnmanagedExports(ImageFileMachine imageFileMachine)1028 		internal void ApplyUnmanagedExports(ImageFileMachine imageFileMachine)
1029 		{
1030 			if (unmanagedExports.Count != 0)
1031 			{
1032 				int type;
1033 				int size;
1034 				switch (imageFileMachine)
1035 				{
1036 					case ImageFileMachine.I386:
1037 					case ImageFileMachine.ARM:
1038 						type = 0x05;
1039 						size = 4;
1040 						break;
1041 					case ImageFileMachine.AMD64:
1042 						type = 0x06;
1043 						size = 8;
1044 						break;
1045 					default:
1046 						throw new NotSupportedException();
1047 				}
1048 				List<MethodBuilder> methods = new List<MethodBuilder>();
1049 				for (int i = 0; i < unmanagedExports.Count; i++)
1050 				{
1051 					if (unmanagedExports[i].mb != null)
1052 					{
1053 						methods.Add(unmanagedExports[i].mb);
1054 					}
1055 				}
1056 				if (methods.Count != 0)
1057 				{
1058 					RelativeVirtualAddress rva = __AddVTableFixups(methods.ToArray(), type);
1059 					for (int i = 0; i < unmanagedExports.Count; i++)
1060 					{
1061 						if (unmanagedExports[i].mb != null)
1062 						{
1063 							UnmanagedExport exp = unmanagedExports[i];
1064 							exp.rva = new RelativeVirtualAddress(rva.initializedDataOffset + (uint)(methods.IndexOf(unmanagedExports[i].mb) * size));
1065 							unmanagedExports[i] = exp;
1066 						}
1067 					}
1068 				}
1069 			}
1070 		}
1071 
FixupMethodBodyTokens()1072 		internal void FixupMethodBodyTokens()
1073 		{
1074 			int methodToken = 0x06000001;
1075 			int fieldToken = 0x04000001;
1076 			int parameterToken = 0x08000001;
1077 			foreach (TypeBuilder type in types)
1078 			{
1079 				type.ResolveMethodAndFieldTokens(ref methodToken, ref fieldToken, ref parameterToken);
1080 			}
1081 			foreach (int offset in tokenFixupOffsets)
1082 			{
1083 				methodBodies.Position = offset;
1084 				int pseudoToken = methodBodies.GetInt32AtCurrentPosition();
1085 				methodBodies.Write(ResolvePseudoToken(pseudoToken));
1086 			}
1087 			foreach (VTableFixups fixup in vtablefixups)
1088 			{
1089 				for (int i = 0; i < fixup.count; i++)
1090 				{
1091 					initializedData.Position = (int)fixup.initializedDataOffset + i * fixup.SlotWidth;
1092 					initializedData.Write(ResolvePseudoToken(initializedData.GetInt32AtCurrentPosition()));
1093 				}
1094 			}
1095 		}
1096 
GetHeaderLength()1097 		private int GetHeaderLength()
1098 		{
1099 			return
1100 				4 + // Signature
1101 				2 + // MajorVersion
1102 				2 + // MinorVersion
1103 				4 + // Reserved
1104 				4 + // ImageRuntimeVersion Length
1105 				StringToPaddedUTF8Length(asm.ImageRuntimeVersion) +
1106 				2 + // Flags
1107 				2 + // Streams
1108 				4 + // #~ Offset
1109 				4 + // #~ Size
1110 				4 + // StringToPaddedUTF8Length("#~")
1111 				4 + // #Strings Offset
1112 				4 + // #Strings Size
1113 				12 + // StringToPaddedUTF8Length("#Strings")
1114 				4 + // #US Offset
1115 				4 + // #US Size
1116 				4 + // StringToPaddedUTF8Length("#US")
1117 				4 + // #GUID Offset
1118 				4 + // #GUID Size
1119 				8 + // StringToPaddedUTF8Length("#GUID")
1120 				(Blobs.IsEmpty ? 0 :
1121 				(
1122 				4 + // #Blob Offset
1123 				4 + // #Blob Size
1124 				8   // StringToPaddedUTF8Length("#Blob")
1125 				));
1126 		}
1127 
1128 		internal int MetadataLength
1129 		{
1130 			get
1131 			{
1132 				return GetHeaderLength() + (Blobs.IsEmpty ? 0 : Blobs.Length) + Tables.Length + Strings.Length + UserStrings.Length + Guids.Length;
1133 			}
1134 		}
1135 
WriteMetadata(MetadataWriter mw, out uint guidHeapOffset)1136 		internal void WriteMetadata(MetadataWriter mw, out uint guidHeapOffset)
1137 		{
1138 			mw.Write(0x424A5342);			// Signature ("BSJB")
1139 			mw.Write((ushort)1);			// MajorVersion
1140 			mw.Write((ushort)1);			// MinorVersion
1141 			mw.Write(0);					// Reserved
1142 			byte[] version = StringToPaddedUTF8(asm.ImageRuntimeVersion);
1143 			mw.Write(version.Length);		// Length
1144 			mw.Write(version);
1145 			mw.Write((ushort)0);			// Flags
1146 			// #Blob is the only optional heap
1147 			if (Blobs.IsEmpty)
1148 			{
1149 				mw.Write((ushort)4);		// Streams
1150 			}
1151 			else
1152 			{
1153 				mw.Write((ushort)5);		// Streams
1154 			}
1155 
1156 			int offset = GetHeaderLength();
1157 
1158 			// Streams
1159 			mw.Write(offset);				// Offset
1160 			mw.Write(Tables.Length);		// Size
1161 			mw.Write(StringToPaddedUTF8("#~"));
1162 			offset += Tables.Length;
1163 
1164 			mw.Write(offset);				// Offset
1165 			mw.Write(Strings.Length);		// Size
1166 			mw.Write(StringToPaddedUTF8("#Strings"));
1167 			offset += Strings.Length;
1168 
1169 			mw.Write(offset);				// Offset
1170 			mw.Write(UserStrings.Length);	// Size
1171 			mw.Write(StringToPaddedUTF8("#US"));
1172 			offset += UserStrings.Length;
1173 
1174 			mw.Write(offset);				// Offset
1175 			mw.Write(Guids.Length);			// Size
1176 			mw.Write(StringToPaddedUTF8("#GUID"));
1177 			offset += Guids.Length;
1178 
1179 			if (!Blobs.IsEmpty)
1180 			{
1181 				mw.Write(offset);				// Offset
1182 				mw.Write(Blobs.Length);			// Size
1183 				mw.Write(StringToPaddedUTF8("#Blob"));
1184 			}
1185 
1186 			Tables.Write(mw);
1187 			Strings.Write(mw);
1188 			UserStrings.Write(mw);
1189 			guidHeapOffset = mw.Position;
1190 			Guids.Write(mw);
1191 			if (!Blobs.IsEmpty)
1192 			{
1193 				Blobs.Write(mw);
1194 			}
1195 		}
1196 
StringToPaddedUTF8Length(string str)1197 		private static int StringToPaddedUTF8Length(string str)
1198 		{
1199 			return (System.Text.Encoding.UTF8.GetByteCount(str) + 4) & ~3;
1200 		}
1201 
StringToPaddedUTF8(string str)1202 		private static byte[] StringToPaddedUTF8(string str)
1203 		{
1204 			byte[] buf = new byte[(System.Text.Encoding.UTF8.GetByteCount(str) + 4) & ~3];
1205 			System.Text.Encoding.UTF8.GetBytes(str, 0, str.Length, buf, 0);
1206 			return buf;
1207 		}
1208 
ExportTypes(int fileToken, ModuleBuilder manifestModule)1209 		internal override void ExportTypes(int fileToken, ModuleBuilder manifestModule)
1210 		{
1211 			manifestModule.ExportTypes(types.ToArray(), fileToken);
1212 		}
1213 
ExportTypes(Type[] types, int fileToken)1214 		internal void ExportTypes(Type[] types, int fileToken)
1215 		{
1216 			Dictionary<Type, int> declaringTypes = new Dictionary<Type, int>();
1217 			foreach (Type type in types)
1218 			{
1219 				if (!type.IsModulePseudoType && IsVisible(type))
1220 				{
1221 					ExportedTypeTable.Record rec = new ExportedTypeTable.Record();
1222 					rec.Flags = (int)type.Attributes;
1223 					// LAMESPEC ECMA says that TypeDefId is a row index, but it should be a token
1224 					rec.TypeDefId = type.MetadataToken;
1225 					SetTypeNameAndTypeNamespace(type.TypeName, out rec.TypeName, out rec.TypeNamespace);
1226 					if (type.IsNested)
1227 					{
1228 						rec.Implementation = declaringTypes[type.DeclaringType];
1229 					}
1230 					else
1231 					{
1232 						rec.Implementation = fileToken;
1233 					}
1234 					int exportTypeToken = 0x27000000 | this.ExportedType.AddRecord(rec);
1235 					declaringTypes.Add(type, exportTypeToken);
1236 				}
1237 			}
1238 		}
1239 
IsVisible(Type type)1240 		private static bool IsVisible(Type type)
1241 		{
1242 			// NOTE this is not the same as Type.IsVisible, because that doesn't take into account family access
1243 			return type.IsPublic || ((type.IsNestedFamily || type.IsNestedFamORAssem || type.IsNestedPublic) && IsVisible(type.DeclaringType));
1244 		}
1245 
AddConstant(int parentToken, object defaultValue)1246 		internal void AddConstant(int parentToken, object defaultValue)
1247 		{
1248 			ConstantTable.Record rec = new ConstantTable.Record();
1249 			rec.Parent = parentToken;
1250 			ByteBuffer val = new ByteBuffer(16);
1251 			if (defaultValue == null)
1252 			{
1253 				rec.Type = Signature.ELEMENT_TYPE_CLASS;
1254 				val.Write((int)0);
1255 			}
1256 			else if (defaultValue is bool)
1257 			{
1258 				rec.Type = Signature.ELEMENT_TYPE_BOOLEAN;
1259 				val.Write((bool)defaultValue ? (byte)1 : (byte)0);
1260 			}
1261 			else if (defaultValue is char)
1262 			{
1263 				rec.Type = Signature.ELEMENT_TYPE_CHAR;
1264 				val.Write((char)defaultValue);
1265 			}
1266 			else if (defaultValue is sbyte)
1267 			{
1268 				rec.Type = Signature.ELEMENT_TYPE_I1;
1269 				val.Write((sbyte)defaultValue);
1270 			}
1271 			else if (defaultValue is byte)
1272 			{
1273 				rec.Type = Signature.ELEMENT_TYPE_U1;
1274 				val.Write((byte)defaultValue);
1275 			}
1276 			else if (defaultValue is short)
1277 			{
1278 				rec.Type = Signature.ELEMENT_TYPE_I2;
1279 				val.Write((short)defaultValue);
1280 			}
1281 			else if (defaultValue is ushort)
1282 			{
1283 				rec.Type = Signature.ELEMENT_TYPE_U2;
1284 				val.Write((ushort)defaultValue);
1285 			}
1286 			else if (defaultValue is int)
1287 			{
1288 				rec.Type = Signature.ELEMENT_TYPE_I4;
1289 				val.Write((int)defaultValue);
1290 			}
1291 			else if (defaultValue is uint)
1292 			{
1293 				rec.Type = Signature.ELEMENT_TYPE_U4;
1294 				val.Write((uint)defaultValue);
1295 			}
1296 			else if (defaultValue is long)
1297 			{
1298 				rec.Type = Signature.ELEMENT_TYPE_I8;
1299 				val.Write((long)defaultValue);
1300 			}
1301 			else if (defaultValue is ulong)
1302 			{
1303 				rec.Type = Signature.ELEMENT_TYPE_U8;
1304 				val.Write((ulong)defaultValue);
1305 			}
1306 			else if (defaultValue is float)
1307 			{
1308 				rec.Type = Signature.ELEMENT_TYPE_R4;
1309 				val.Write((float)defaultValue);
1310 			}
1311 			else if (defaultValue is double)
1312 			{
1313 				rec.Type = Signature.ELEMENT_TYPE_R8;
1314 				val.Write((double)defaultValue);
1315 			}
1316 			else if (defaultValue is string)
1317 			{
1318 				rec.Type = Signature.ELEMENT_TYPE_STRING;
1319 				foreach (char c in (string)defaultValue)
1320 				{
1321 					val.Write(c);
1322 				}
1323 			}
1324 			else if (defaultValue is DateTime)
1325 			{
1326 				rec.Type = Signature.ELEMENT_TYPE_I8;
1327 				val.Write(((DateTime)defaultValue).Ticks);
1328 			}
1329 			else
1330 			{
1331 				throw new ArgumentException();
1332 			}
1333 			rec.Value = this.Blobs.Add(val);
1334 			this.Constant.AddRecord(rec);
1335 		}
1336 
1337 		ModuleBuilder ITypeOwner.ModuleBuilder
1338 		{
1339 			get { return this; }
1340 		}
1341 
ResolveType(int metadataToken, IGenericContext context)1342 		internal override Type ResolveType(int metadataToken, IGenericContext context)
1343 		{
1344 			if (metadataToken >> 24 != TypeDefTable.Index)
1345 			{
1346 				throw new NotImplementedException();
1347 			}
1348 			return types[(metadataToken & 0xFFFFFF) - 1];
1349 		}
1350 
ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)1351 		public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1352 		{
1353 			if (genericTypeArguments != null || genericMethodArguments != null)
1354 			{
1355 				throw new NotImplementedException();
1356 			}
1357 			// this method is inefficient, but since it isn't used we don't care
1358 			if ((metadataToken >> 24) == MemberRefTable.Index)
1359 			{
1360 				foreach (KeyValuePair<MemberRefKey, int> kv in importedMemberRefs)
1361 				{
1362 					if (kv.Value == metadataToken)
1363 					{
1364 						return kv.Key.LookupMethod();
1365 					}
1366 				}
1367 			}
1368 			// HACK if we're given a SymbolToken, we need to convert back
1369 			if ((metadataToken & 0xFF000000) == 0x06000000)
1370 			{
1371 				metadataToken = -(metadataToken & 0x00FFFFFF);
1372 			}
1373 			foreach (Type type in types)
1374 			{
1375 				MethodBase method = ((TypeBuilder)type).LookupMethod(metadataToken);
1376 				if (method != null)
1377 				{
1378 					return method;
1379 				}
1380 			}
1381 			return ((TypeBuilder)moduleType).LookupMethod(metadataToken);
1382 		}
1383 
ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)1384 		public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1385 		{
1386 			throw new NotImplementedException();
1387 		}
1388 
ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)1389 		public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
1390 		{
1391 			throw new NotImplementedException();
1392 		}
1393 
ResolveString(int metadataToken)1394 		public override string ResolveString(int metadataToken)
1395 		{
1396 			throw new NotImplementedException();
1397 		}
1398 
1399 		public override string FullyQualifiedName
1400 		{
1401 			get { return Path.GetFullPath(Path.Combine(asm.dir, fileName)); }
1402 		}
1403 
1404 		public override string Name
1405 		{
1406 			get { return fileName; }
1407 		}
1408 
GetModuleVersionIdOrEmpty()1409 		internal Guid GetModuleVersionIdOrEmpty()
1410 		{
1411 			return mvid;
1412 		}
1413 
1414 		public override Guid ModuleVersionId
1415 		{
1416 			get
1417 			{
1418 				if (mvid == Guid.Empty && universe.Deterministic)
1419 				{
1420 					// if a deterministic GUID is used, it can't be queried before the assembly has been written
1421 					throw new InvalidOperationException();
1422 				}
1423 				return mvid;
1424 			}
1425 		}
1426 
__SetModuleVersionId(Guid guid)1427 		public void __SetModuleVersionId(Guid guid)
1428 		{
1429 			if (guid == Guid.Empty && universe.Deterministic)
1430 			{
1431 				// if you want to use Guid.Empty, don't set UniverseOptions.DeterministicOutput
1432 				throw new ArgumentOutOfRangeException();
1433 			}
1434 			mvid = guid;
1435 		}
1436 
GetTimeDateStamp()1437 		internal uint GetTimeDateStamp()
1438 		{
1439 			return timestamp;
1440 		}
1441 
1442 		public DateTime __PEHeaderTimeDateStamp
1443 		{
1444 			get { return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(timestamp); }
1445 			set
1446 			{
1447 				if (value < new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc) || value > new DateTime(2106, 2, 7, 6, 28, 15, DateTimeKind.Utc))
1448 				{
1449 					throw new ArgumentOutOfRangeException();
1450 				}
1451 				timestamp = (uint)(value - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
1452 			}
1453 		}
1454 
__ResolveOptionalParameterTypes(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments, out CustomModifiers[] customModifiers)1455 		public override Type[] __ResolveOptionalParameterTypes(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments, out CustomModifiers[] customModifiers)
1456 		{
1457 			throw new NotImplementedException();
1458 		}
1459 
1460 		public override string ScopeName
1461 		{
1462 			get { return moduleName; }
1463 		}
1464 
1465 #if !NO_SYMBOL_WRITER
GetSymWriter()1466 		public ISymbolWriter GetSymWriter()
1467 		{
1468 			return symbolWriter;
1469 		}
1470 #endif
1471 
DefineUnmanagedResource(string resourceFileName)1472 		public void DefineUnmanagedResource(string resourceFileName)
1473 		{
1474 			// This method reads the specified resource file (Win32 .res file) and converts it into the appropriate format and embeds it in the .rsrc section,
1475 			// also setting the Resource Directory entry.
1476 			unmanagedResources = new ResourceSection();
1477 			unmanagedResources.ExtractResources(System.IO.File.ReadAllBytes(resourceFileName));
1478 		}
1479 
IsTransient()1480 		public bool IsTransient()
1481 		{
1482 			return false;
1483 		}
1484 
SetUserEntryPoint(MethodInfo entryPoint)1485 		public void SetUserEntryPoint(MethodInfo entryPoint)
1486 		{
1487 			int token = entryPoint.MetadataToken;
1488 			if (token < 0)
1489 			{
1490 				token = -token | 0x06000000;
1491 			}
1492 #if !NO_SYMBOL_WRITER
1493 			if (symbolWriter != null)
1494 			{
1495 				symbolWriter.SetUserEntryPoint(new SymbolToken(token));
1496 			}
1497 #endif
1498 		}
1499 
GetStringConstant(string str)1500 		public StringToken GetStringConstant(string str)
1501 		{
1502 			return new StringToken(this.UserStrings.Add(str) | (0x70 << 24));
1503 		}
1504 
GetSignatureToken(SignatureHelper sigHelper)1505 		public SignatureToken GetSignatureToken(SignatureHelper sigHelper)
1506 		{
1507 			return new SignatureToken(this.StandAloneSig.FindOrAddRecord(this.Blobs.Add(sigHelper.GetSignature(this))) | (StandAloneSigTable.Index << 24));
1508 		}
1509 
GetSignatureToken(byte[] sigBytes, int sigLength)1510 		public SignatureToken GetSignatureToken(byte[] sigBytes, int sigLength)
1511 		{
1512 			return new SignatureToken(this.StandAloneSig.FindOrAddRecord(this.Blobs.Add(ByteBuffer.Wrap(sigBytes, sigLength))) | (StandAloneSigTable.Index << 24));
1513 		}
1514 
GetArrayMethod(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)1515 		public MethodInfo GetArrayMethod(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
1516 		{
1517 			return new ArrayMethod(this, arrayClass, methodName, callingConvention, returnType, parameterTypes);
1518 		}
1519 
GetArrayMethodToken(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)1520 		public MethodToken GetArrayMethodToken(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
1521 		{
1522 			return GetMethodToken(GetArrayMethod(arrayClass, methodName, callingConvention, returnType, parameterTypes));
1523 		}
1524 
GetModuleType()1525 		internal override Type GetModuleType()
1526 		{
1527 			return moduleType;
1528 		}
1529 
GetBlob(int blobIndex)1530 		internal override IKVM.Reflection.Reader.ByteReader GetBlob(int blobIndex)
1531 		{
1532 			return Blobs.GetBlob(blobIndex);
1533 		}
1534 
GetGuid(int guidIndex)1535 		internal sealed override Guid GetGuid(int guidIndex)
1536 		{
1537 			throw new NotImplementedException();
1538 		}
1539 
GetSignatureBlobIndex(Signature sig)1540 		internal int GetSignatureBlobIndex(Signature sig)
1541 		{
1542 			ByteBuffer bb = new ByteBuffer(16);
1543 			sig.WriteSig(this, bb);
1544 			return this.Blobs.Add(bb);
1545 		}
1546 
1547 		// non-standard API
1548 		public new long __ImageBase
1549 		{
1550 			get { return imageBaseAddress; }
1551 			set { imageBaseAddress = value; }
1552 		}
1553 
GetImageBaseImpl()1554 		protected override long GetImageBaseImpl()
1555 		{
1556 			return imageBaseAddress;
1557 		}
1558 
1559 		public new long __StackReserve
1560 		{
1561 			get { return stackReserve; }
1562 			set { stackReserve = value; }
1563 		}
1564 
GetStackReserveImpl()1565 		protected override long GetStackReserveImpl()
1566 		{
1567 			return stackReserve;
1568 		}
1569 
1570 		[Obsolete("Use __StackReserve property.")]
__SetStackReserve(long stackReserve)1571 		public void __SetStackReserve(long stackReserve)
1572 		{
1573 			__StackReserve = stackReserve;
1574 		}
1575 
GetStackReserve(ulong defaultValue)1576 		internal ulong GetStackReserve(ulong defaultValue)
1577 		{
1578 			return stackReserve == -1 ? defaultValue : (ulong)stackReserve;
1579 		}
1580 
1581 		public new int __FileAlignment
1582 		{
1583 			get { return fileAlignment; }
1584 			set { fileAlignment = value; }
1585 		}
1586 
GetFileAlignmentImpl()1587 		protected override int GetFileAlignmentImpl()
1588 		{
1589 			return fileAlignment;
1590 		}
1591 
1592 		public new DllCharacteristics __DllCharacteristics
1593 		{
1594 			get { return dllCharacteristics; }
1595 			set { dllCharacteristics = value; }
1596 		}
1597 
GetDllCharacteristicsImpl()1598 		protected override DllCharacteristics GetDllCharacteristicsImpl()
1599 		{
1600 			return dllCharacteristics;
1601 		}
1602 
1603 		public override int MDStreamVersion
1604 		{
1605 			get { return asm.mdStreamVersion; }
1606 		}
1607 
AddTypeRefByName(int resolutionScope, string ns, string name)1608 		private int AddTypeRefByName(int resolutionScope, string ns, string name)
1609 		{
1610 			TypeRefTable.Record rec = new TypeRefTable.Record();
1611 			rec.ResolutionScope = resolutionScope;
1612 			SetTypeNameAndTypeNamespace(new TypeName(ns, name), out rec.TypeName, out rec.TypeNamespace);
1613 			return 0x01000000 | this.TypeRef.AddRecord(rec);
1614 		}
1615 
__Save(PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)1616 		public void __Save(PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1617 		{
1618 			SaveImpl(null, portableExecutableKind, imageFileMachine);
1619 		}
1620 
__Save(Stream stream, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)1621 		public void __Save(Stream stream, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1622 		{
1623 			if (!stream.CanRead || !stream.CanWrite || !stream.CanSeek || stream.Position != 0)
1624 			{
1625 				throw new ArgumentException("Stream must support read/write/seek and current position must be zero.", "stream");
1626 			}
1627 			SaveImpl(stream, portableExecutableKind, imageFileMachine);
1628 		}
1629 
SaveImpl(Stream streamOrNull, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)1630 		private void SaveImpl(Stream streamOrNull, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
1631 		{
1632 			SetIsSaved();
1633 			PopulatePropertyAndEventTables();
1634 			IList<CustomAttributeData> attributes = asm.GetCustomAttributesData(null);
1635 			if (attributes.Count > 0)
1636 			{
1637 				int mscorlib = ImportAssemblyRef(universe.Mscorlib);
1638 				int[] placeholderTokens = new int[4];
1639 				string[] placeholderTypeNames = new string[] { "AssemblyAttributesGoHere", "AssemblyAttributesGoHereM", "AssemblyAttributesGoHereS", "AssemblyAttributesGoHereSM" };
1640 				foreach (CustomAttributeData cad in attributes)
1641 				{
1642 					int index;
1643 					if (cad.Constructor.DeclaringType.BaseType == universe.System_Security_Permissions_CodeAccessSecurityAttribute)
1644 					{
1645 						if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute)
1646 						{
1647 							index = 3;
1648 						}
1649 						else
1650 						{
1651 							index = 2;
1652 						}
1653 					}
1654 					else if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute)
1655 					{
1656 						index = 1;
1657 					}
1658 					else
1659 					{
1660 						index = 0;
1661 					}
1662 					if (placeholderTokens[index] == 0)
1663 					{
1664 						// we manually add a TypeRef without looking it up in mscorlib, because Mono and Silverlight's mscorlib don't have these types
1665 						placeholderTokens[index] = AddTypeRefByName(mscorlib, "System.Runtime.CompilerServices", placeholderTypeNames[index]);
1666 					}
1667 					SetCustomAttribute(placeholderTokens[index], cad.__ToBuilder());
1668 				}
1669 			}
1670 			FillAssemblyRefTable();
1671 			EmitResources();
1672 			ModuleWriter.WriteModule(null, null, this, PEFileKinds.Dll, portableExecutableKind, imageFileMachine, unmanagedResources, 0, streamOrNull);
1673 			CloseResources();
1674 		}
1675 
__AddAssemblyReference(AssemblyName assemblyName)1676 		public void __AddAssemblyReference(AssemblyName assemblyName)
1677 		{
1678 			__AddAssemblyReference(assemblyName, null);
1679 		}
1680 
__AddAssemblyReference(AssemblyName assemblyName, Assembly assembly)1681 		public void __AddAssemblyReference(AssemblyName assemblyName, Assembly assembly)
1682 		{
1683 			if (referencedAssemblyNames == null)
1684 			{
1685 				referencedAssemblyNames = new List<AssemblyName>();
1686 			}
1687 			referencedAssemblyNames.Add((AssemblyName)assemblyName.Clone());
1688 			int token = FindOrAddAssemblyRef(assemblyName, true);
1689 			if (assembly != null)
1690 			{
1691 				referencedAssemblies.Add(assembly, token);
1692 			}
1693 		}
1694 
__GetReferencedAssemblies()1695 		public override AssemblyName[] __GetReferencedAssemblies()
1696 		{
1697 			List<AssemblyName> list = new List<AssemblyName>();
1698 			if (referencedAssemblyNames != null)
1699 			{
1700 				foreach (AssemblyName name in referencedAssemblyNames)
1701 				{
1702 					if (!list.Contains(name))
1703 					{
1704 						list.Add(name);
1705 					}
1706 				}
1707 			}
1708 			foreach (Assembly asm in referencedAssemblies.Keys)
1709 			{
1710 				AssemblyName name = asm.GetName();
1711 				if (!list.Contains(name))
1712 				{
1713 					list.Add(name);
1714 				}
1715 			}
1716 			return list.ToArray();
1717 		}
1718 
__AddModuleReference(string module)1719 		public void __AddModuleReference(string module)
1720 		{
1721 			this.ModuleRef.FindOrAddRecord(module == null ? 0 : this.Strings.Add(module));
1722 		}
1723 
__GetReferencedModules()1724 		public override string[] __GetReferencedModules()
1725 		{
1726 			string[] arr = new string[this.ModuleRef.RowCount];
1727 			for (int i = 0; i < arr.Length; i++)
1728 			{
1729 				arr[i] = this.Strings.Find(this.ModuleRef.records[i]);
1730 			}
1731 			return arr;
1732 		}
1733 
__GetReferencedTypes()1734 		public override Type[] __GetReferencedTypes()
1735 		{
1736 			List<Type> list = new List<Type>();
1737 			foreach (KeyValuePair<Type, int> kv in typeTokens)
1738 			{
1739 				if (kv.Value >> 24 == TypeRefTable.Index)
1740 				{
1741 					list.Add(kv.Key);
1742 				}
1743 			}
1744 			return list.ToArray();
1745 		}
1746 
__GetExportedTypes()1747 		public override Type[] __GetExportedTypes()
1748 		{
1749 			throw new NotImplementedException();
1750 		}
1751 
__AddModule(int flags, string name, byte[] hash)1752 		public int __AddModule(int flags, string name, byte[] hash)
1753 		{
1754 			FileTable.Record file = new FileTable.Record();
1755 			file.Flags = flags;
1756 			file.Name = this.Strings.Add(name);
1757 			file.HashValue = this.Blobs.Add(ByteBuffer.Wrap(hash));
1758 			return 0x26000000 + this.File.AddRecord(file);
1759 		}
1760 
__AddManifestResource(int offset, ResourceAttributes flags, string name, int implementation)1761 		public int __AddManifestResource(int offset, ResourceAttributes flags, string name, int implementation)
1762 		{
1763 			ManifestResourceTable.Record res = new ManifestResourceTable.Record();
1764 			res.Offset = offset;
1765 			res.Flags = (int)flags;
1766 			res.Name = this.Strings.Add(name);
1767 			res.Implementation = implementation;
1768 			return 0x28000000 + this.ManifestResource.AddRecord(res);
1769 		}
1770 
__SetCustomAttributeFor(int token, CustomAttributeBuilder customBuilder)1771 		public void __SetCustomAttributeFor(int token, CustomAttributeBuilder customBuilder)
1772 		{
1773 			SetCustomAttribute(token, customBuilder);
1774 		}
1775 
__AddVTableFixups(MethodBuilder[] methods, int type)1776 		public RelativeVirtualAddress __AddVTableFixups(MethodBuilder[] methods, int type)
1777 		{
1778 			initializedData.Align(8);
1779 			VTableFixups fixups;
1780 			fixups.initializedDataOffset = (uint)initializedData.Position;
1781 			fixups.count = (ushort)methods.Length;
1782 			fixups.type = (ushort)type;
1783 			foreach (MethodBuilder mb in methods)
1784 			{
1785 				initializedData.Write(mb.MetadataToken);
1786 				if (fixups.SlotWidth == 8)
1787 				{
1788 					initializedData.Write(0);
1789 				}
1790 			}
1791 			vtablefixups.Add(fixups);
1792 			return new RelativeVirtualAddress(fixups.initializedDataOffset);
1793 		}
1794 
__AddUnmanagedExportStub(string name, int ordinal, RelativeVirtualAddress rva)1795 		public void __AddUnmanagedExportStub(string name, int ordinal, RelativeVirtualAddress rva)
1796 		{
1797 			AddUnmanagedExport(name, ordinal, null, rva);
1798 		}
1799 
AddUnmanagedExport(string name, int ordinal, MethodBuilder methodBuilder, RelativeVirtualAddress rva)1800 		internal void AddUnmanagedExport(string name, int ordinal, MethodBuilder methodBuilder, RelativeVirtualAddress rva)
1801 		{
1802 			UnmanagedExport export;
1803 			export.name = name;
1804 			export.ordinal = ordinal;
1805 			export.mb = methodBuilder;
1806 			export.rva = rva;
1807 			unmanagedExports.Add(export);
1808 		}
1809 
SetInterfaceImplementationCustomAttribute(TypeBuilder typeBuilder, Type interfaceType, CustomAttributeBuilder cab)1810 		internal void SetInterfaceImplementationCustomAttribute(TypeBuilder typeBuilder, Type interfaceType, CustomAttributeBuilder cab)
1811 		{
1812 			// NOTE since interfaceimpls are extremely common and custom attributes on them are extremely rare,
1813 			// we store (and resolve) the custom attributes in such away as to avoid impacting the common case performance
1814 			if (interfaceImplCustomAttributes == null)
1815 			{
1816 				interfaceImplCustomAttributes = new List<InterfaceImplCustomAttribute>();
1817 			}
1818 			InterfaceImplCustomAttribute rec;
1819 			rec.type = typeBuilder.MetadataToken;
1820 			int token = GetTypeToken(interfaceType).Token;
1821 			switch (token >> 24)
1822 			{
1823 				case TypeDefTable.Index:
1824 					token = (token & 0xFFFFFF) << 2 | 0;
1825 					break;
1826 				case TypeRefTable.Index:
1827 					token = (token & 0xFFFFFF) << 2 | 1;
1828 					break;
1829 				case TypeSpecTable.Index:
1830 					token = (token & 0xFFFFFF) << 2 | 2;
1831 					break;
1832 				default:
1833 					throw new InvalidOperationException();
1834 			}
1835 			rec.interfaceType = token;
1836 			rec.pseudoToken = AllocPseudoToken();
1837 			interfaceImplCustomAttributes.Add(rec);
1838 			SetCustomAttribute(rec.pseudoToken, cab);
1839 		}
1840 
ResolveInterfaceImplPseudoTokens()1841 		internal void ResolveInterfaceImplPseudoTokens()
1842 		{
1843 			if (interfaceImplCustomAttributes != null)
1844 			{
1845 				foreach (InterfaceImplCustomAttribute rec in interfaceImplCustomAttributes)
1846 				{
1847 					for (int i = 0; i < InterfaceImpl.records.Length; i++)
1848 					{
1849 						if (InterfaceImpl.records[i].Class == rec.type && InterfaceImpl.records[i].Interface == rec.interfaceType)
1850 						{
1851 							RegisterTokenFixup(rec.pseudoToken, (InterfaceImplTable.Index << 24) | (i + 1));
1852 							break;
1853 						}
1854 					}
1855 				}
1856 			}
1857 		}
1858 
FixupPseudoToken(ref int token)1859 		internal void FixupPseudoToken(ref int token)
1860 		{
1861 			if (IsPseudoToken(token))
1862 			{
1863 				token = ResolvePseudoToken(token);
1864 			}
1865 		}
1866 
SetIsSaved()1867 		internal void SetIsSaved()
1868 		{
1869 			if (saved)
1870 			{
1871 				throw new InvalidOperationException();
1872 			}
1873 			saved = true;
1874 		}
1875 
1876 		internal bool IsSaved
1877 		{
1878 			get { return saved; }
1879 		}
1880 
GetString(int index)1881 		internal override string GetString(int index)
1882 		{
1883 			return this.Strings.Find(index);
1884 		}
1885 	}
1886 
1887 	struct UnmanagedExport
1888 	{
1889 		internal string name;
1890 		internal int ordinal;
1891 		internal RelativeVirtualAddress rva;
1892 		internal MethodBuilder mb;
1893 	}
1894 
1895 	public struct RelativeVirtualAddress
1896 	{
1897 		internal readonly uint initializedDataOffset;
1898 
RelativeVirtualAddressIKVM.Reflection.Emit.RelativeVirtualAddress1899 		internal RelativeVirtualAddress(uint initializedDataOffset)
1900 		{
1901 			this.initializedDataOffset = initializedDataOffset;
1902 		}
1903 
operator +IKVM.Reflection.Emit.RelativeVirtualAddress1904 		public static RelativeVirtualAddress operator +(RelativeVirtualAddress rva, int offset)
1905 		{
1906 			return new RelativeVirtualAddress(rva.initializedDataOffset + (uint)offset);
1907 		}
1908 	}
1909 
1910 	class ArrayMethod : MethodInfo
1911 	{
1912 		private readonly Module module;
1913 		private readonly Type arrayClass;
1914 		private readonly string methodName;
1915 		private readonly CallingConventions callingConvention;
1916 		private readonly Type returnType;
1917 		protected readonly Type[] parameterTypes;
1918 		private MethodSignature methodSignature;
1919 
ArrayMethod(Module module, Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)1920 		internal ArrayMethod(Module module, Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
1921 		{
1922 			this.module = module;
1923 			this.arrayClass = arrayClass;
1924 			this.methodName = methodName;
1925 			this.callingConvention = callingConvention;
1926 			this.returnType = returnType ?? module.universe.System_Void;
1927 			this.parameterTypes = Util.Copy(parameterTypes);
1928 		}
1929 
GetMethodBody()1930 		public override MethodBody GetMethodBody()
1931 		{
1932 			throw new InvalidOperationException();
1933 		}
1934 
1935 		public override int __MethodRVA
1936 		{
1937 			get { throw new InvalidOperationException(); }
1938 		}
1939 
GetMethodImplementationFlags()1940 		public override MethodImplAttributes GetMethodImplementationFlags()
1941 		{
1942 			throw new NotSupportedException();
1943 		}
1944 
GetParameters()1945 		public override ParameterInfo[] GetParameters()
1946 		{
1947 			throw new NotSupportedException();
1948 		}
1949 
ImportTo(ModuleBuilder module)1950 		internal override int ImportTo(ModuleBuilder module)
1951 		{
1952 			return module.ImportMethodOrField(arrayClass, methodName, MethodSignature);
1953 		}
1954 
1955 		public override MethodAttributes Attributes
1956 		{
1957 			get { throw new NotSupportedException(); }
1958 		}
1959 
1960 		public override CallingConventions CallingConvention
1961 		{
1962 			get { return callingConvention; }
1963 		}
1964 
1965 		public override Type DeclaringType
1966 		{
1967 			get { return arrayClass; }
1968 		}
1969 
1970 		internal override MethodSignature MethodSignature
1971 		{
1972 			get
1973 			{
1974 				if (methodSignature == null)
1975 				{
1976 					methodSignature = MethodSignature.MakeFromBuilder(returnType, parameterTypes, new PackedCustomModifiers(), callingConvention, 0);
1977 				}
1978 				return methodSignature;
1979 			}
1980 		}
1981 
1982 		public override Module Module
1983 		{
1984 			// FXBUG like .NET, we return the module that GetArrayMethod was called on, not the module associated with the array type
1985 			get { return module; }
1986 		}
1987 
1988 		public override string Name
1989 		{
1990 			get { return methodName; }
1991 		}
1992 
1993 		internal override int ParameterCount
1994 		{
1995 			get { return parameterTypes.Length; }
1996 		}
1997 
1998 		public override ParameterInfo ReturnParameter
1999 		{
2000 			// FXBUG like .NET, we throw NotImplementedException
2001 			get { throw new NotImplementedException(); }
2002 		}
2003 
2004 		public override Type ReturnType
2005 		{
2006 			get { return returnType; }
2007 		}
2008 
2009 		internal override bool HasThis
2010 		{
2011 			get { return (callingConvention & (CallingConventions.HasThis | CallingConventions.ExplicitThis)) == CallingConventions.HasThis; }
2012 		}
2013 
GetCurrentToken()2014 		internal override int GetCurrentToken()
2015 		{
2016 			return this.MetadataToken;
2017 		}
2018 
2019 		internal override bool IsBaked
2020 		{
2021 			get { return arrayClass.IsBaked; }
2022 		}
2023 	}
2024 }
2025