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