1 // 2 // Author: 3 // Jb Evain (jbevain@gmail.com) 4 // 5 // Copyright (c) 2008 - 2015 Jb Evain 6 // Copyright (c) 2008 - 2011 Novell, Inc. 7 // 8 // Licensed under the MIT/X11 license. 9 // 10 11 using System; 12 using System.Collections.Generic; 13 using System.IO; 14 using System.IO.Compression; 15 using System.Text; 16 17 using Mono.Collections.Generic; 18 using Mono.Cecil.Cil; 19 using Mono.Cecil.Metadata; 20 using Mono.Cecil.PE; 21 22 using RVA = System.UInt32; 23 24 namespace Mono.Cecil { 25 26 abstract class ModuleReader { 27 28 readonly protected ModuleDefinition module; 29 ModuleReader(Image image, ReadingMode mode)30 protected ModuleReader (Image image, ReadingMode mode) 31 { 32 this.module = new ModuleDefinition (image); 33 this.module.ReadingMode = mode; 34 } 35 ReadModule()36 protected abstract void ReadModule (); ReadSymbols(ModuleDefinition module)37 public abstract void ReadSymbols (ModuleDefinition module); 38 ReadModuleManifest(MetadataReader reader)39 protected void ReadModuleManifest (MetadataReader reader) 40 { 41 reader.Populate (module); 42 43 ReadAssembly (reader); 44 } 45 ReadAssembly(MetadataReader reader)46 void ReadAssembly (MetadataReader reader) 47 { 48 var name = reader.ReadAssemblyNameDefinition (); 49 if (name == null) { 50 module.kind = ModuleKind.NetModule; 51 return; 52 } 53 54 var assembly = new AssemblyDefinition (); 55 assembly.Name = name; 56 57 module.assembly = assembly; 58 assembly.main_module = module; 59 } 60 CreateModule(Image image, ReaderParameters parameters)61 public static ModuleDefinition CreateModule (Image image, ReaderParameters parameters) 62 { 63 var reader = CreateModuleReader (image, parameters.ReadingMode); 64 var module = reader.module; 65 66 if (parameters.assembly_resolver != null) 67 module.assembly_resolver = Disposable.NotOwned (parameters.assembly_resolver); 68 69 if (parameters.metadata_resolver != null) 70 module.metadata_resolver = parameters.metadata_resolver; 71 72 #if !READ_ONLY 73 if (parameters.metadata_importer_provider != null) 74 module.metadata_importer = parameters.metadata_importer_provider.GetMetadataImporter (module); 75 if (parameters.reflection_importer_provider != null) 76 module.reflection_importer = parameters.reflection_importer_provider.GetReflectionImporter (module); 77 #endif 78 79 GetMetadataKind (module, parameters); 80 81 reader.ReadModule (); 82 83 ReadSymbols (module, parameters); 84 85 reader.ReadSymbols (module); 86 87 if (parameters.ReadingMode == ReadingMode.Immediate) 88 module.MetadataSystem.Clear (); 89 90 return module; 91 } 92 ReadSymbols(ModuleDefinition module, ReaderParameters parameters)93 static void ReadSymbols (ModuleDefinition module, ReaderParameters parameters) 94 { 95 var symbol_reader_provider = parameters.SymbolReaderProvider; 96 97 if (symbol_reader_provider == null && parameters.ReadSymbols) 98 symbol_reader_provider = new DefaultSymbolReaderProvider (); 99 100 if (symbol_reader_provider != null) { 101 module.SymbolReaderProvider = symbol_reader_provider; 102 103 var reader = parameters.SymbolStream != null 104 ? symbol_reader_provider.GetSymbolReader (module, parameters.SymbolStream) 105 : symbol_reader_provider.GetSymbolReader (module, module.FileName); 106 107 if (reader != null) 108 module.ReadSymbols (reader); 109 } 110 111 if (module.Image.HasDebugTables ()) 112 module.ReadSymbols (new PortablePdbReader (module.Image, module)); 113 } 114 GetMetadataKind(ModuleDefinition module, ReaderParameters parameters)115 static void GetMetadataKind (ModuleDefinition module, ReaderParameters parameters) 116 { 117 if (!parameters.ApplyWindowsRuntimeProjections) { 118 module.MetadataKind = MetadataKind.Ecma335; 119 return; 120 } 121 122 var runtime_version = module.RuntimeVersion; 123 124 if (!runtime_version.Contains ("WindowsRuntime")) 125 module.MetadataKind = MetadataKind.Ecma335; 126 else if (runtime_version.Contains ("CLR")) 127 module.MetadataKind = MetadataKind.ManagedWindowsMetadata; 128 else 129 module.MetadataKind = MetadataKind.WindowsMetadata; 130 } 131 CreateModuleReader(Image image, ReadingMode mode)132 static ModuleReader CreateModuleReader (Image image, ReadingMode mode) 133 { 134 switch (mode) { 135 case ReadingMode.Immediate: 136 return new ImmediateModuleReader (image); 137 case ReadingMode.Deferred: 138 return new DeferredModuleReader (image); 139 default: 140 throw new ArgumentException (); 141 } 142 } 143 } 144 145 sealed class ImmediateModuleReader : ModuleReader { 146 147 bool resolve_attributes; 148 ImmediateModuleReader(Image image)149 public ImmediateModuleReader (Image image) 150 : base (image, ReadingMode.Immediate) 151 { 152 } 153 ReadModule()154 protected override void ReadModule () 155 { 156 this.module.Read (this.module, (module, reader) => { 157 ReadModuleManifest (reader); 158 ReadModule (module, resolve_attributes: true); 159 }); 160 } 161 ReadModule(ModuleDefinition module, bool resolve_attributes)162 public void ReadModule (ModuleDefinition module, bool resolve_attributes) 163 { 164 this.resolve_attributes = resolve_attributes; 165 166 if (module.HasAssemblyReferences) 167 Mixin.Read (module.AssemblyReferences); 168 if (module.HasResources) 169 Mixin.Read (module.Resources); 170 if (module.HasModuleReferences) 171 Mixin.Read (module.ModuleReferences); 172 if (module.HasTypes) 173 ReadTypes (module.Types); 174 if (module.HasExportedTypes) 175 Mixin.Read (module.ExportedTypes); 176 177 ReadCustomAttributes (module); 178 179 var assembly = module.Assembly; 180 if (assembly == null) 181 return; 182 183 ReadCustomAttributes (assembly); 184 ReadSecurityDeclarations (assembly); 185 } 186 ReadTypes(Collection<TypeDefinition> types)187 void ReadTypes (Collection<TypeDefinition> types) 188 { 189 for (int i = 0; i < types.Count; i++) 190 ReadType (types [i]); 191 } 192 ReadType(TypeDefinition type)193 void ReadType (TypeDefinition type) 194 { 195 ReadGenericParameters (type); 196 197 if (type.HasInterfaces) 198 ReadInterfaces (type); 199 200 if (type.HasNestedTypes) 201 ReadTypes (type.NestedTypes); 202 203 if (type.HasLayoutInfo) 204 Mixin.Read (type.ClassSize); 205 206 if (type.HasFields) 207 ReadFields (type); 208 209 if (type.HasMethods) 210 ReadMethods (type); 211 212 if (type.HasProperties) 213 ReadProperties (type); 214 215 if (type.HasEvents) 216 ReadEvents (type); 217 218 ReadSecurityDeclarations (type); 219 ReadCustomAttributes (type); 220 } 221 ReadInterfaces(TypeDefinition type)222 void ReadInterfaces (TypeDefinition type) 223 { 224 var interfaces = type.Interfaces; 225 226 for (int i = 0; i < interfaces.Count; i++) 227 ReadCustomAttributes (interfaces [i]); 228 } 229 ReadGenericParameters(IGenericParameterProvider provider)230 void ReadGenericParameters (IGenericParameterProvider provider) 231 { 232 if (!provider.HasGenericParameters) 233 return; 234 235 var parameters = provider.GenericParameters; 236 237 for (int i = 0; i < parameters.Count; i++) { 238 var parameter = parameters [i]; 239 240 if (parameter.HasConstraints) 241 Mixin.Read (parameter.Constraints); 242 243 ReadCustomAttributes (parameter); 244 } 245 } 246 ReadSecurityDeclarations(ISecurityDeclarationProvider provider)247 void ReadSecurityDeclarations (ISecurityDeclarationProvider provider) 248 { 249 if (!provider.HasSecurityDeclarations) 250 return; 251 252 var security_declarations = provider.SecurityDeclarations; 253 254 if (!resolve_attributes) 255 return; 256 257 for (int i = 0; i < security_declarations.Count; i++) { 258 var security_declaration = security_declarations [i]; 259 260 Mixin.Read (security_declaration.SecurityAttributes); 261 } 262 } 263 ReadCustomAttributes(ICustomAttributeProvider provider)264 void ReadCustomAttributes (ICustomAttributeProvider provider) 265 { 266 if (!provider.HasCustomAttributes) 267 return; 268 269 var custom_attributes = provider.CustomAttributes; 270 271 if (!resolve_attributes) 272 return; 273 274 for (int i = 0; i < custom_attributes.Count; i++) { 275 var custom_attribute = custom_attributes [i]; 276 277 Mixin.Read (custom_attribute.ConstructorArguments); 278 } 279 } 280 ReadFields(TypeDefinition type)281 void ReadFields (TypeDefinition type) 282 { 283 var fields = type.Fields; 284 285 for (int i = 0; i < fields.Count; i++) { 286 var field = fields [i]; 287 288 if (field.HasConstant) 289 Mixin.Read (field.Constant); 290 291 if (field.HasLayoutInfo) 292 Mixin.Read (field.Offset); 293 294 if (field.RVA > 0) 295 Mixin.Read (field.InitialValue); 296 297 if (field.HasMarshalInfo) 298 Mixin.Read (field.MarshalInfo); 299 300 ReadCustomAttributes (field); 301 } 302 } 303 ReadMethods(TypeDefinition type)304 void ReadMethods (TypeDefinition type) 305 { 306 var methods = type.Methods; 307 308 for (int i = 0; i < methods.Count; i++) { 309 var method = methods [i]; 310 311 ReadGenericParameters (method); 312 313 if (method.HasParameters) 314 ReadParameters (method); 315 316 if (method.HasOverrides) 317 Mixin.Read (method.Overrides); 318 319 if (method.IsPInvokeImpl) 320 Mixin.Read (method.PInvokeInfo); 321 322 ReadSecurityDeclarations (method); 323 ReadCustomAttributes (method); 324 325 var return_type = method.MethodReturnType; 326 if (return_type.HasConstant) 327 Mixin.Read (return_type.Constant); 328 329 if (return_type.HasMarshalInfo) 330 Mixin.Read (return_type.MarshalInfo); 331 332 ReadCustomAttributes (return_type); 333 } 334 } 335 ReadParameters(MethodDefinition method)336 void ReadParameters (MethodDefinition method) 337 { 338 var parameters = method.Parameters; 339 340 for (int i = 0; i < parameters.Count; i++) { 341 var parameter = parameters [i]; 342 343 if (parameter.HasConstant) 344 Mixin.Read (parameter.Constant); 345 346 if (parameter.HasMarshalInfo) 347 Mixin.Read (parameter.MarshalInfo); 348 349 ReadCustomAttributes (parameter); 350 } 351 } 352 ReadProperties(TypeDefinition type)353 void ReadProperties (TypeDefinition type) 354 { 355 var properties = type.Properties; 356 357 for (int i = 0; i < properties.Count; i++) { 358 var property = properties [i]; 359 360 Mixin.Read (property.GetMethod); 361 362 if (property.HasConstant) 363 Mixin.Read (property.Constant); 364 365 ReadCustomAttributes (property); 366 } 367 } 368 ReadEvents(TypeDefinition type)369 void ReadEvents (TypeDefinition type) 370 { 371 var events = type.Events; 372 373 for (int i = 0; i < events.Count; i++) { 374 var @event = events [i]; 375 376 Mixin.Read (@event.AddMethod); 377 378 ReadCustomAttributes (@event); 379 } 380 } 381 ReadSymbols(ModuleDefinition module)382 public override void ReadSymbols (ModuleDefinition module) 383 { 384 if (module.symbol_reader == null) 385 return; 386 387 ReadTypesSymbols (module.Types, module.symbol_reader); 388 } 389 ReadTypesSymbols(Collection<TypeDefinition> types, ISymbolReader symbol_reader)390 void ReadTypesSymbols (Collection<TypeDefinition> types, ISymbolReader symbol_reader) 391 { 392 for (int i = 0; i < types.Count; i++) { 393 var type = types [i]; 394 395 if (type.HasNestedTypes) 396 ReadTypesSymbols (type.NestedTypes, symbol_reader); 397 398 if (type.HasMethods) 399 ReadMethodsSymbols (type, symbol_reader); 400 } 401 } 402 ReadMethodsSymbols(TypeDefinition type, ISymbolReader symbol_reader)403 void ReadMethodsSymbols (TypeDefinition type, ISymbolReader symbol_reader) 404 { 405 var methods = type.Methods; 406 for (int i = 0; i < methods.Count; i++) { 407 var method = methods [i]; 408 409 if (method.HasBody && method.token.RID != 0 && method.debug_info == null) 410 method.debug_info = symbol_reader.Read (method); 411 } 412 } 413 } 414 415 sealed class DeferredModuleReader : ModuleReader { 416 DeferredModuleReader(Image image)417 public DeferredModuleReader (Image image) 418 : base (image, ReadingMode.Deferred) 419 { 420 } 421 ReadModule()422 protected override void ReadModule () 423 { 424 this.module.Read (this.module, (_, reader) => ReadModuleManifest (reader)); 425 } 426 ReadSymbols(ModuleDefinition module)427 public override void ReadSymbols (ModuleDefinition module) 428 { 429 } 430 } 431 432 sealed class MetadataReader : ByteBuffer { 433 434 readonly internal Image image; 435 readonly internal ModuleDefinition module; 436 readonly internal MetadataSystem metadata; 437 438 internal CodeReader code; 439 internal IGenericContext context; 440 441 readonly MetadataReader metadata_reader; 442 MetadataReader(ModuleDefinition module)443 public MetadataReader (ModuleDefinition module) 444 : base (module.Image.TableHeap.data) 445 { 446 this.image = module.Image; 447 this.module = module; 448 this.metadata = module.MetadataSystem; 449 this.code = new CodeReader (this); 450 } 451 MetadataReader(Image image, ModuleDefinition module, MetadataReader metadata_reader)452 public MetadataReader (Image image, ModuleDefinition module, MetadataReader metadata_reader) 453 : base (image.TableHeap.data) 454 { 455 this.image = image; 456 this.module = module; 457 this.metadata = module.MetadataSystem; 458 this.metadata_reader = metadata_reader; 459 } 460 GetCodedIndexSize(CodedIndex index)461 int GetCodedIndexSize (CodedIndex index) 462 { 463 return image.GetCodedIndexSize (index); 464 } 465 ReadByIndexSize(int size)466 uint ReadByIndexSize (int size) 467 { 468 if (size == 4) 469 return ReadUInt32 (); 470 else 471 return ReadUInt16 (); 472 } 473 ReadBlob()474 byte [] ReadBlob () 475 { 476 var blob_heap = image.BlobHeap; 477 if (blob_heap == null) { 478 position += 2; 479 return Empty<byte>.Array; 480 } 481 482 return blob_heap.Read (ReadBlobIndex ()); 483 } 484 ReadBlob(uint signature)485 byte [] ReadBlob (uint signature) 486 { 487 var blob_heap = image.BlobHeap; 488 if (blob_heap == null) 489 return Empty<byte>.Array; 490 491 return blob_heap.Read (signature); 492 } 493 ReadBlobIndex()494 uint ReadBlobIndex () 495 { 496 var blob_heap = image.BlobHeap; 497 return ReadByIndexSize (blob_heap != null ? blob_heap.IndexSize : 2); 498 } 499 GetBlobView(uint signature, out byte [] blob, out int index, out int count)500 void GetBlobView (uint signature, out byte [] blob, out int index, out int count) 501 { 502 var blob_heap = image.BlobHeap; 503 if (blob_heap == null) { 504 blob = null; 505 index = count = 0; 506 return; 507 } 508 509 blob_heap.GetView (signature, out blob, out index, out count); 510 } 511 ReadString()512 string ReadString () 513 { 514 return image.StringHeap.Read (ReadByIndexSize (image.StringHeap.IndexSize)); 515 } 516 ReadStringIndex()517 uint ReadStringIndex () 518 { 519 return ReadByIndexSize (image.StringHeap.IndexSize); 520 } 521 ReadGuid()522 Guid ReadGuid () 523 { 524 return image.GuidHeap.Read (ReadByIndexSize (image.GuidHeap.IndexSize)); 525 } 526 ReadTableIndex(Table table)527 uint ReadTableIndex (Table table) 528 { 529 return ReadByIndexSize (image.GetTableIndexSize (table)); 530 } 531 ReadMetadataToken(CodedIndex index)532 MetadataToken ReadMetadataToken (CodedIndex index) 533 { 534 return index.GetMetadataToken (ReadByIndexSize (GetCodedIndexSize (index))); 535 } 536 MoveTo(Table table)537 int MoveTo (Table table) 538 { 539 var info = image.TableHeap [table]; 540 if (info.Length != 0) 541 this.position = (int) info.Offset; 542 543 return (int) info.Length; 544 } 545 MoveTo(Table table, uint row)546 bool MoveTo (Table table, uint row) 547 { 548 var info = image.TableHeap [table]; 549 var length = info.Length; 550 if (length == 0 || row > length) 551 return false; 552 553 this.position = (int) (info.Offset + (info.RowSize * (row - 1))); 554 return true; 555 } 556 ReadAssemblyNameDefinition()557 public AssemblyNameDefinition ReadAssemblyNameDefinition () 558 { 559 if (MoveTo (Table.Assembly) == 0) 560 return null; 561 562 var name = new AssemblyNameDefinition (); 563 564 name.HashAlgorithm = (AssemblyHashAlgorithm) ReadUInt32 (); 565 566 PopulateVersionAndFlags (name); 567 568 name.PublicKey = ReadBlob (); 569 570 PopulateNameAndCulture (name); 571 572 return name; 573 } 574 Populate(ModuleDefinition module)575 public ModuleDefinition Populate (ModuleDefinition module) 576 { 577 if (MoveTo (Table.Module) == 0) 578 return module; 579 580 Advance (2); // Generation 581 582 module.Name = ReadString (); 583 module.Mvid = ReadGuid (); 584 585 return module; 586 } 587 InitializeAssemblyReferences()588 void InitializeAssemblyReferences () 589 { 590 if (metadata.AssemblyReferences != null) 591 return; 592 593 int length = MoveTo (Table.AssemblyRef); 594 var references = metadata.AssemblyReferences = new AssemblyNameReference [length]; 595 596 for (uint i = 0; i < length; i++) { 597 var reference = new AssemblyNameReference (); 598 reference.token = new MetadataToken (TokenType.AssemblyRef, i + 1); 599 600 PopulateVersionAndFlags (reference); 601 602 var key_or_token = ReadBlob (); 603 604 if (reference.HasPublicKey) 605 reference.PublicKey = key_or_token; 606 else 607 reference.PublicKeyToken = key_or_token; 608 609 PopulateNameAndCulture (reference); 610 611 reference.Hash = ReadBlob (); 612 613 references [i] = reference; 614 } 615 } 616 ReadAssemblyReferences()617 public Collection<AssemblyNameReference> ReadAssemblyReferences () 618 { 619 InitializeAssemblyReferences (); 620 621 var references = new Collection<AssemblyNameReference> (metadata.AssemblyReferences); 622 if (module.IsWindowsMetadata ()) 623 module.Projections.AddVirtualReferences (references); 624 625 return references; 626 } 627 ReadEntryPoint()628 public MethodDefinition ReadEntryPoint () 629 { 630 if (module.Image.EntryPointToken == 0) 631 return null; 632 633 var token = new MetadataToken (module.Image.EntryPointToken); 634 return GetMethodDefinition (token.RID); 635 } 636 ReadModules()637 public Collection<ModuleDefinition> ReadModules () 638 { 639 var modules = new Collection<ModuleDefinition> (1); 640 modules.Add (this.module); 641 642 int length = MoveTo (Table.File); 643 for (uint i = 1; i <= length; i++) { 644 var attributes = (FileAttributes) ReadUInt32 (); 645 var name = ReadString (); 646 ReadBlobIndex (); 647 648 if (attributes != FileAttributes.ContainsMetaData) 649 continue; 650 651 var parameters = new ReaderParameters { 652 ReadingMode = module.ReadingMode, 653 SymbolReaderProvider = module.SymbolReaderProvider, 654 AssemblyResolver = module.AssemblyResolver 655 }; 656 657 modules.Add (ModuleDefinition.ReadModule ( 658 GetModuleFileName (name), parameters)); 659 } 660 661 return modules; 662 } 663 GetModuleFileName(string name)664 string GetModuleFileName (string name) 665 { 666 if (module.FileName == null) 667 throw new NotSupportedException (); 668 669 var path = Path.GetDirectoryName (module.FileName); 670 return Path.Combine (path, name); 671 } 672 InitializeModuleReferences()673 void InitializeModuleReferences () 674 { 675 if (metadata.ModuleReferences != null) 676 return; 677 678 int length = MoveTo (Table.ModuleRef); 679 var references = metadata.ModuleReferences = new ModuleReference [length]; 680 681 for (uint i = 0; i < length; i++) { 682 var reference = new ModuleReference (ReadString ()); 683 reference.token = new MetadataToken (TokenType.ModuleRef, i + 1); 684 685 references [i] = reference; 686 } 687 } 688 ReadModuleReferences()689 public Collection<ModuleReference> ReadModuleReferences () 690 { 691 InitializeModuleReferences (); 692 693 return new Collection<ModuleReference> (metadata.ModuleReferences); 694 } 695 HasFileResource()696 public bool HasFileResource () 697 { 698 int length = MoveTo (Table.File); 699 if (length == 0) 700 return false; 701 702 for (uint i = 1; i <= length; i++) 703 if (ReadFileRecord (i).Col1 == FileAttributes.ContainsNoMetaData) 704 return true; 705 706 return false; 707 } 708 ReadResources()709 public Collection<Resource> ReadResources () 710 { 711 int length = MoveTo (Table.ManifestResource); 712 var resources = new Collection<Resource> (length); 713 714 for (int i = 1; i <= length; i++) { 715 var offset = ReadUInt32 (); 716 var flags = (ManifestResourceAttributes) ReadUInt32 (); 717 var name = ReadString (); 718 var implementation = ReadMetadataToken (CodedIndex.Implementation); 719 720 Resource resource; 721 722 if (implementation.RID == 0) { 723 resource = new EmbeddedResource (name, flags, offset, this); 724 } else if (implementation.TokenType == TokenType.AssemblyRef) { 725 resource = new AssemblyLinkedResource (name, flags) { 726 Assembly = (AssemblyNameReference) GetTypeReferenceScope (implementation), 727 }; 728 } else if (implementation.TokenType == TokenType.File) { 729 var file_record = ReadFileRecord (implementation.RID); 730 731 resource = new LinkedResource (name, flags) { 732 File = file_record.Col2, 733 hash = ReadBlob (file_record.Col3) 734 }; 735 } else 736 continue; 737 738 resources.Add (resource); 739 } 740 741 return resources; 742 } 743 ReadFileRecord(uint rid)744 Row<FileAttributes, string, uint> ReadFileRecord (uint rid) 745 { 746 var position = this.position; 747 748 if (!MoveTo (Table.File, rid)) 749 throw new ArgumentException (); 750 751 var record = new Row<FileAttributes, string, uint> ( 752 (FileAttributes) ReadUInt32 (), 753 ReadString (), 754 ReadBlobIndex ()); 755 756 this.position = position; 757 758 return record; 759 } 760 GetManagedResource(uint offset)761 public byte [] GetManagedResource (uint offset) 762 { 763 return image.GetReaderAt (image.Resources.VirtualAddress, offset, (o, reader) => { 764 reader.Advance ((int) o); 765 return reader.ReadBytes (reader.ReadInt32 ()); 766 }) ?? Empty<byte>.Array; 767 } 768 PopulateVersionAndFlags(AssemblyNameReference name)769 void PopulateVersionAndFlags (AssemblyNameReference name) 770 { 771 name.Version = new Version ( 772 ReadUInt16 (), 773 ReadUInt16 (), 774 ReadUInt16 (), 775 ReadUInt16 ()); 776 777 name.Attributes = (AssemblyAttributes) ReadUInt32 (); 778 } 779 PopulateNameAndCulture(AssemblyNameReference name)780 void PopulateNameAndCulture (AssemblyNameReference name) 781 { 782 name.Name = ReadString (); 783 name.Culture = ReadString (); 784 } 785 ReadTypes()786 public TypeDefinitionCollection ReadTypes () 787 { 788 InitializeTypeDefinitions (); 789 var mtypes = metadata.Types; 790 var type_count = mtypes.Length - metadata.NestedTypes.Count; 791 var types = new TypeDefinitionCollection (module, type_count); 792 793 for (int i = 0; i < mtypes.Length; i++) { 794 var type = mtypes [i]; 795 if (IsNested (type.Attributes)) 796 continue; 797 798 types.Add (type); 799 } 800 801 if (image.HasTable (Table.MethodPtr) || image.HasTable (Table.FieldPtr)) 802 CompleteTypes (); 803 804 return types; 805 } 806 CompleteTypes()807 void CompleteTypes () 808 { 809 var types = metadata.Types; 810 811 for (int i = 0; i < types.Length; i++) { 812 var type = types [i]; 813 814 Mixin.Read (type.Fields); 815 Mixin.Read (type.Methods); 816 } 817 } 818 InitializeTypeDefinitions()819 void InitializeTypeDefinitions () 820 { 821 if (metadata.Types != null) 822 return; 823 824 InitializeNestedTypes (); 825 InitializeFields (); 826 InitializeMethods (); 827 828 int length = MoveTo (Table.TypeDef); 829 var types = metadata.Types = new TypeDefinition [length]; 830 831 for (uint i = 0; i < length; i++) { 832 if (types [i] != null) 833 continue; 834 835 types [i] = ReadType (i + 1); 836 } 837 } 838 IsNested(TypeAttributes attributes)839 static bool IsNested (TypeAttributes attributes) 840 { 841 switch (attributes & TypeAttributes.VisibilityMask) { 842 case TypeAttributes.NestedAssembly: 843 case TypeAttributes.NestedFamANDAssem: 844 case TypeAttributes.NestedFamily: 845 case TypeAttributes.NestedFamORAssem: 846 case TypeAttributes.NestedPrivate: 847 case TypeAttributes.NestedPublic: 848 return true; 849 default: 850 return false; 851 } 852 } 853 HasNestedTypes(TypeDefinition type)854 public bool HasNestedTypes (TypeDefinition type) 855 { 856 Collection<uint> mapping; 857 InitializeNestedTypes (); 858 859 if (!metadata.TryGetNestedTypeMapping (type, out mapping)) 860 return false; 861 862 return mapping.Count > 0; 863 } 864 ReadNestedTypes(TypeDefinition type)865 public Collection<TypeDefinition> ReadNestedTypes (TypeDefinition type) 866 { 867 InitializeNestedTypes (); 868 Collection<uint> mapping; 869 if (!metadata.TryGetNestedTypeMapping (type, out mapping)) 870 return new MemberDefinitionCollection<TypeDefinition> (type); 871 872 var nested_types = new MemberDefinitionCollection<TypeDefinition> (type, mapping.Count); 873 874 for (int i = 0; i < mapping.Count; i++) { 875 var nested_type = GetTypeDefinition (mapping [i]); 876 877 if (nested_type != null) 878 nested_types.Add (nested_type); 879 } 880 881 metadata.RemoveNestedTypeMapping (type); 882 883 return nested_types; 884 } 885 InitializeNestedTypes()886 void InitializeNestedTypes () 887 { 888 if (metadata.NestedTypes != null) 889 return; 890 891 var length = MoveTo (Table.NestedClass); 892 893 metadata.NestedTypes = new Dictionary<uint, Collection<uint>> (length); 894 metadata.ReverseNestedTypes = new Dictionary<uint, uint> (length); 895 896 if (length == 0) 897 return; 898 899 for (int i = 1; i <= length; i++) { 900 var nested = ReadTableIndex (Table.TypeDef); 901 var declaring = ReadTableIndex (Table.TypeDef); 902 903 AddNestedMapping (declaring, nested); 904 } 905 } 906 AddNestedMapping(uint declaring, uint nested)907 void AddNestedMapping (uint declaring, uint nested) 908 { 909 metadata.SetNestedTypeMapping (declaring, AddMapping (metadata.NestedTypes, declaring, nested)); 910 metadata.SetReverseNestedTypeMapping (nested, declaring); 911 } 912 AddMapping(Dictionary<TKey, Collection<TValue>> cache, TKey key, TValue value)913 static Collection<TValue> AddMapping<TKey, TValue> (Dictionary<TKey, Collection<TValue>> cache, TKey key, TValue value) 914 { 915 Collection<TValue> mapped; 916 if (!cache.TryGetValue (key, out mapped)) { 917 mapped = new Collection<TValue> (); 918 } 919 mapped.Add (value); 920 return mapped; 921 } 922 ReadType(uint rid)923 TypeDefinition ReadType (uint rid) 924 { 925 if (!MoveTo (Table.TypeDef, rid)) 926 return null; 927 928 var attributes = (TypeAttributes) ReadUInt32 (); 929 var name = ReadString (); 930 var @namespace = ReadString (); 931 var type = new TypeDefinition (@namespace, name, attributes); 932 type.token = new MetadataToken (TokenType.TypeDef, rid); 933 type.scope = module; 934 type.module = module; 935 936 metadata.AddTypeDefinition (type); 937 938 this.context = type; 939 940 type.BaseType = GetTypeDefOrRef (ReadMetadataToken (CodedIndex.TypeDefOrRef)); 941 942 type.fields_range = ReadListRange (rid, Table.TypeDef, Table.Field); 943 type.methods_range = ReadListRange (rid, Table.TypeDef, Table.Method); 944 945 if (IsNested (attributes)) 946 type.DeclaringType = GetNestedTypeDeclaringType (type); 947 948 if (module.IsWindowsMetadata ()) 949 WindowsRuntimeProjections.Project (type); 950 951 return type; 952 } 953 GetNestedTypeDeclaringType(TypeDefinition type)954 TypeDefinition GetNestedTypeDeclaringType (TypeDefinition type) 955 { 956 uint declaring_rid; 957 if (!metadata.TryGetReverseNestedTypeMapping (type, out declaring_rid)) 958 return null; 959 960 metadata.RemoveReverseNestedTypeMapping (type); 961 return GetTypeDefinition (declaring_rid); 962 } 963 ReadListRange(uint current_index, Table current, Table target)964 Range ReadListRange (uint current_index, Table current, Table target) 965 { 966 var list = new Range (); 967 968 var start = ReadTableIndex (target); 969 if (start == 0) 970 return list; 971 972 uint next_index; 973 var current_table = image.TableHeap [current]; 974 975 if (current_index == current_table.Length) 976 next_index = image.TableHeap [target].Length + 1; 977 else { 978 var position = this.position; 979 this.position += (int) (current_table.RowSize - image.GetTableIndexSize (target)); 980 next_index = ReadTableIndex (target); 981 this.position = position; 982 } 983 984 list.Start = start; 985 list.Length = next_index - start; 986 987 return list; 988 } 989 ReadTypeLayout(TypeDefinition type)990 public Row<short, int> ReadTypeLayout (TypeDefinition type) 991 { 992 InitializeTypeLayouts (); 993 Row<ushort, uint> class_layout; 994 var rid = type.token.RID; 995 if (!metadata.ClassLayouts.TryGetValue (rid, out class_layout)) 996 return new Row<short, int> (Mixin.NoDataMarker, Mixin.NoDataMarker); 997 998 type.PackingSize = (short) class_layout.Col1; 999 type.ClassSize = (int) class_layout.Col2; 1000 1001 metadata.ClassLayouts.Remove (rid); 1002 1003 return new Row<short, int> ((short) class_layout.Col1, (int) class_layout.Col2); 1004 } 1005 InitializeTypeLayouts()1006 void InitializeTypeLayouts () 1007 { 1008 if (metadata.ClassLayouts != null) 1009 return; 1010 1011 int length = MoveTo (Table.ClassLayout); 1012 1013 var class_layouts = metadata.ClassLayouts = new Dictionary<uint, Row<ushort, uint>> (length); 1014 1015 for (uint i = 0; i < length; i++) { 1016 var packing_size = ReadUInt16 (); 1017 var class_size = ReadUInt32 (); 1018 1019 var parent = ReadTableIndex (Table.TypeDef); 1020 1021 class_layouts.Add (parent, new Row<ushort, uint> (packing_size, class_size)); 1022 } 1023 } 1024 GetTypeDefOrRef(MetadataToken token)1025 public TypeReference GetTypeDefOrRef (MetadataToken token) 1026 { 1027 return (TypeReference) LookupToken (token); 1028 } 1029 GetTypeDefinition(uint rid)1030 public TypeDefinition GetTypeDefinition (uint rid) 1031 { 1032 InitializeTypeDefinitions (); 1033 1034 var type = metadata.GetTypeDefinition (rid); 1035 if (type != null) 1036 return type; 1037 1038 return ReadTypeDefinition (rid); 1039 } 1040 ReadTypeDefinition(uint rid)1041 TypeDefinition ReadTypeDefinition (uint rid) 1042 { 1043 if (!MoveTo (Table.TypeDef, rid)) 1044 return null; 1045 1046 return ReadType (rid); 1047 } 1048 InitializeTypeReferences()1049 void InitializeTypeReferences () 1050 { 1051 if (metadata.TypeReferences != null) 1052 return; 1053 1054 metadata.TypeReferences = new TypeReference [image.GetTableLength (Table.TypeRef)]; 1055 } 1056 GetTypeReference(string scope, string full_name)1057 public TypeReference GetTypeReference (string scope, string full_name) 1058 { 1059 InitializeTypeReferences (); 1060 1061 var length = metadata.TypeReferences.Length; 1062 1063 for (uint i = 1; i <= length; i++) { 1064 var type = GetTypeReference (i); 1065 1066 if (type.FullName != full_name) 1067 continue; 1068 1069 if (string.IsNullOrEmpty (scope)) 1070 return type; 1071 1072 if (type.Scope.Name == scope) 1073 return type; 1074 } 1075 1076 return null; 1077 } 1078 GetTypeReference(uint rid)1079 TypeReference GetTypeReference (uint rid) 1080 { 1081 InitializeTypeReferences (); 1082 1083 var type = metadata.GetTypeReference (rid); 1084 if (type != null) 1085 return type; 1086 1087 return ReadTypeReference (rid); 1088 } 1089 ReadTypeReference(uint rid)1090 TypeReference ReadTypeReference (uint rid) 1091 { 1092 if (!MoveTo (Table.TypeRef, rid)) 1093 return null; 1094 1095 TypeReference declaring_type = null; 1096 IMetadataScope scope; 1097 1098 var scope_token = ReadMetadataToken (CodedIndex.ResolutionScope); 1099 1100 var name = ReadString (); 1101 var @namespace = ReadString (); 1102 1103 var type = new TypeReference ( 1104 @namespace, 1105 name, 1106 module, 1107 null); 1108 1109 type.token = new MetadataToken (TokenType.TypeRef, rid); 1110 1111 metadata.AddTypeReference (type); 1112 1113 if (scope_token.TokenType == TokenType.TypeRef) { 1114 declaring_type = GetTypeDefOrRef (scope_token); 1115 1116 scope = declaring_type != null 1117 ? declaring_type.Scope 1118 : module; 1119 } else 1120 scope = GetTypeReferenceScope (scope_token); 1121 1122 type.scope = scope; 1123 type.DeclaringType = declaring_type; 1124 1125 MetadataSystem.TryProcessPrimitiveTypeReference (type); 1126 1127 if (type.Module.IsWindowsMetadata ()) 1128 WindowsRuntimeProjections.Project (type); 1129 1130 return type; 1131 } 1132 GetTypeReferenceScope(MetadataToken scope)1133 IMetadataScope GetTypeReferenceScope (MetadataToken scope) 1134 { 1135 if (scope.TokenType == TokenType.Module) 1136 return module; 1137 1138 IMetadataScope[] scopes; 1139 1140 switch (scope.TokenType) { 1141 case TokenType.AssemblyRef: 1142 InitializeAssemblyReferences (); 1143 scopes = metadata.AssemblyReferences; 1144 break; 1145 case TokenType.ModuleRef: 1146 InitializeModuleReferences (); 1147 scopes = metadata.ModuleReferences; 1148 break; 1149 default: 1150 throw new NotSupportedException (); 1151 } 1152 1153 var index = scope.RID - 1; 1154 if (index < 0 || index >= scopes.Length) 1155 return null; 1156 1157 return scopes [index]; 1158 } 1159 GetTypeReferences()1160 public IEnumerable<TypeReference> GetTypeReferences () 1161 { 1162 InitializeTypeReferences (); 1163 1164 var length = image.GetTableLength (Table.TypeRef); 1165 1166 var type_references = new TypeReference [length]; 1167 1168 for (uint i = 1; i <= length; i++) 1169 type_references [i - 1] = GetTypeReference (i); 1170 1171 return type_references; 1172 } 1173 GetTypeSpecification(uint rid)1174 TypeReference GetTypeSpecification (uint rid) 1175 { 1176 if (!MoveTo (Table.TypeSpec, rid)) 1177 return null; 1178 1179 var reader = ReadSignature (ReadBlobIndex ()); 1180 var type = reader.ReadTypeSignature (); 1181 if (type.token.RID == 0) 1182 type.token = new MetadataToken (TokenType.TypeSpec, rid); 1183 1184 return type; 1185 } 1186 ReadSignature(uint signature)1187 SignatureReader ReadSignature (uint signature) 1188 { 1189 return new SignatureReader (signature, this); 1190 } 1191 HasInterfaces(TypeDefinition type)1192 public bool HasInterfaces (TypeDefinition type) 1193 { 1194 InitializeInterfaces (); 1195 Collection<Row<uint, MetadataToken>> mapping; 1196 1197 return metadata.TryGetInterfaceMapping (type, out mapping); 1198 } 1199 ReadInterfaces(TypeDefinition type)1200 public InterfaceImplementationCollection ReadInterfaces (TypeDefinition type) 1201 { 1202 InitializeInterfaces (); 1203 Collection<Row<uint, MetadataToken>> mapping; 1204 1205 if (!metadata.TryGetInterfaceMapping (type, out mapping)) 1206 return new InterfaceImplementationCollection (type); 1207 1208 var interfaces = new InterfaceImplementationCollection (type, mapping.Count); 1209 1210 this.context = type; 1211 1212 for (int i = 0; i < mapping.Count; i++) { 1213 interfaces.Add ( 1214 new InterfaceImplementation ( 1215 GetTypeDefOrRef (mapping [i].Col2), 1216 new MetadataToken(TokenType.InterfaceImpl, mapping [i].Col1))); 1217 } 1218 1219 metadata.RemoveInterfaceMapping (type); 1220 1221 return interfaces; 1222 } 1223 InitializeInterfaces()1224 void InitializeInterfaces () 1225 { 1226 if (metadata.Interfaces != null) 1227 return; 1228 1229 int length = MoveTo (Table.InterfaceImpl); 1230 1231 metadata.Interfaces = new Dictionary<uint, Collection<Row<uint, MetadataToken>>> (length); 1232 1233 for (uint i = 1; i <= length; i++) { 1234 var type = ReadTableIndex (Table.TypeDef); 1235 var @interface = ReadMetadataToken (CodedIndex.TypeDefOrRef); 1236 1237 AddInterfaceMapping (type, new Row<uint, MetadataToken> (i, @interface)); 1238 } 1239 } 1240 AddInterfaceMapping(uint type, Row<uint, MetadataToken> @interface)1241 void AddInterfaceMapping (uint type, Row<uint, MetadataToken> @interface) 1242 { 1243 metadata.SetInterfaceMapping (type, AddMapping (metadata.Interfaces, type, @interface)); 1244 } 1245 ReadFields(TypeDefinition type)1246 public Collection<FieldDefinition> ReadFields (TypeDefinition type) 1247 { 1248 var fields_range = type.fields_range; 1249 if (fields_range.Length == 0) 1250 return new MemberDefinitionCollection<FieldDefinition> (type); 1251 1252 var fields = new MemberDefinitionCollection<FieldDefinition> (type, (int) fields_range.Length); 1253 this.context = type; 1254 1255 if (!MoveTo (Table.FieldPtr, fields_range.Start)) { 1256 if (!MoveTo (Table.Field, fields_range.Start)) 1257 return fields; 1258 1259 for (uint i = 0; i < fields_range.Length; i++) 1260 ReadField (fields_range.Start + i, fields); 1261 } else 1262 ReadPointers (Table.FieldPtr, Table.Field, fields_range, fields, ReadField); 1263 1264 return fields; 1265 } 1266 ReadField(uint field_rid, Collection<FieldDefinition> fields)1267 void ReadField (uint field_rid, Collection<FieldDefinition> fields) 1268 { 1269 var attributes = (FieldAttributes) ReadUInt16 (); 1270 var name = ReadString (); 1271 var signature = ReadBlobIndex (); 1272 1273 var field = new FieldDefinition (name, attributes, ReadFieldType (signature)); 1274 field.token = new MetadataToken (TokenType.Field, field_rid); 1275 metadata.AddFieldDefinition (field); 1276 1277 if (IsDeleted (field)) 1278 return; 1279 1280 fields.Add (field); 1281 1282 if (module.IsWindowsMetadata ()) 1283 WindowsRuntimeProjections.Project (field); 1284 } 1285 InitializeFields()1286 void InitializeFields () 1287 { 1288 if (metadata.Fields != null) 1289 return; 1290 1291 metadata.Fields = new FieldDefinition [image.GetTableLength (Table.Field)]; 1292 } 1293 ReadFieldType(uint signature)1294 TypeReference ReadFieldType (uint signature) 1295 { 1296 var reader = ReadSignature (signature); 1297 1298 const byte field_sig = 0x6; 1299 1300 if (reader.ReadByte () != field_sig) 1301 throw new NotSupportedException (); 1302 1303 return reader.ReadTypeSignature (); 1304 } 1305 ReadFieldRVA(FieldDefinition field)1306 public int ReadFieldRVA (FieldDefinition field) 1307 { 1308 InitializeFieldRVAs (); 1309 var rid = field.token.RID; 1310 1311 RVA rva; 1312 if (!metadata.FieldRVAs.TryGetValue (rid, out rva)) 1313 return 0; 1314 1315 var size = GetFieldTypeSize (field.FieldType); 1316 1317 if (size == 0 || rva == 0) 1318 return 0; 1319 1320 metadata.FieldRVAs.Remove (rid); 1321 1322 field.InitialValue = GetFieldInitializeValue (size, rva); 1323 1324 return (int) rva; 1325 } 1326 GetFieldInitializeValue(int size, RVA rva)1327 byte [] GetFieldInitializeValue (int size, RVA rva) 1328 { 1329 return image.GetReaderAt (rva, size, (s, reader) => reader.ReadBytes (s)) ?? Empty<byte>.Array; 1330 } 1331 GetFieldTypeSize(TypeReference type)1332 static int GetFieldTypeSize (TypeReference type) 1333 { 1334 int size = 0; 1335 1336 switch (type.etype) { 1337 case ElementType.Boolean: 1338 case ElementType.U1: 1339 case ElementType.I1: 1340 size = 1; 1341 break; 1342 case ElementType.U2: 1343 case ElementType.I2: 1344 case ElementType.Char: 1345 size = 2; 1346 break; 1347 case ElementType.U4: 1348 case ElementType.I4: 1349 case ElementType.R4: 1350 size = 4; 1351 break; 1352 case ElementType.U8: 1353 case ElementType.I8: 1354 case ElementType.R8: 1355 size = 8; 1356 break; 1357 case ElementType.Ptr: 1358 case ElementType.FnPtr: 1359 size = IntPtr.Size; 1360 break; 1361 case ElementType.CModOpt: 1362 case ElementType.CModReqD: 1363 return GetFieldTypeSize (((IModifierType) type).ElementType); 1364 default: 1365 var field_type = type.Resolve (); 1366 if (field_type != null && field_type.HasLayoutInfo) 1367 size = field_type.ClassSize; 1368 1369 break; 1370 } 1371 1372 return size; 1373 } 1374 InitializeFieldRVAs()1375 void InitializeFieldRVAs () 1376 { 1377 if (metadata.FieldRVAs != null) 1378 return; 1379 1380 int length = MoveTo (Table.FieldRVA); 1381 1382 var field_rvas = metadata.FieldRVAs = new Dictionary<uint, uint> (length); 1383 1384 for (int i = 0; i < length; i++) { 1385 var rva = ReadUInt32 (); 1386 var field = ReadTableIndex (Table.Field); 1387 1388 field_rvas.Add (field, rva); 1389 } 1390 } 1391 ReadFieldLayout(FieldDefinition field)1392 public int ReadFieldLayout (FieldDefinition field) 1393 { 1394 InitializeFieldLayouts (); 1395 var rid = field.token.RID; 1396 uint offset; 1397 if (!metadata.FieldLayouts.TryGetValue (rid, out offset)) 1398 return Mixin.NoDataMarker; 1399 1400 metadata.FieldLayouts.Remove (rid); 1401 1402 return (int) offset; 1403 } 1404 InitializeFieldLayouts()1405 void InitializeFieldLayouts () 1406 { 1407 if (metadata.FieldLayouts != null) 1408 return; 1409 1410 int length = MoveTo (Table.FieldLayout); 1411 1412 var field_layouts = metadata.FieldLayouts = new Dictionary<uint, uint> (length); 1413 1414 for (int i = 0; i < length; i++) { 1415 var offset = ReadUInt32 (); 1416 var field = ReadTableIndex (Table.Field); 1417 1418 field_layouts.Add (field, offset); 1419 } 1420 } 1421 HasEvents(TypeDefinition type)1422 public bool HasEvents (TypeDefinition type) 1423 { 1424 InitializeEvents (); 1425 1426 Range range; 1427 if (!metadata.TryGetEventsRange (type, out range)) 1428 return false; 1429 1430 return range.Length > 0; 1431 } 1432 ReadEvents(TypeDefinition type)1433 public Collection<EventDefinition> ReadEvents (TypeDefinition type) 1434 { 1435 InitializeEvents (); 1436 Range range; 1437 1438 if (!metadata.TryGetEventsRange (type, out range)) 1439 return new MemberDefinitionCollection<EventDefinition> (type); 1440 1441 var events = new MemberDefinitionCollection<EventDefinition> (type, (int) range.Length); 1442 1443 metadata.RemoveEventsRange (type); 1444 1445 if (range.Length == 0) 1446 return events; 1447 1448 this.context = type; 1449 1450 if (!MoveTo (Table.EventPtr, range.Start)) { 1451 if (!MoveTo (Table.Event, range.Start)) 1452 return events; 1453 1454 for (uint i = 0; i < range.Length; i++) 1455 ReadEvent (range.Start + i, events); 1456 } else 1457 ReadPointers (Table.EventPtr, Table.Event, range, events, ReadEvent); 1458 1459 return events; 1460 } 1461 ReadEvent(uint event_rid, Collection<EventDefinition> events)1462 void ReadEvent (uint event_rid, Collection<EventDefinition> events) 1463 { 1464 var attributes = (EventAttributes) ReadUInt16 (); 1465 var name = ReadString (); 1466 var event_type = GetTypeDefOrRef (ReadMetadataToken (CodedIndex.TypeDefOrRef)); 1467 1468 var @event = new EventDefinition (name, attributes, event_type); 1469 @event.token = new MetadataToken (TokenType.Event, event_rid); 1470 1471 if (IsDeleted (@event)) 1472 return; 1473 1474 events.Add (@event); 1475 } 1476 InitializeEvents()1477 void InitializeEvents () 1478 { 1479 if (metadata.Events != null) 1480 return; 1481 1482 int length = MoveTo (Table.EventMap); 1483 1484 metadata.Events = new Dictionary<uint, Range> (length); 1485 1486 for (uint i = 1; i <= length; i++) { 1487 var type_rid = ReadTableIndex (Table.TypeDef); 1488 Range events_range = ReadListRange (i, Table.EventMap, Table.Event); 1489 metadata.AddEventsRange (type_rid, events_range); 1490 } 1491 } 1492 HasProperties(TypeDefinition type)1493 public bool HasProperties (TypeDefinition type) 1494 { 1495 InitializeProperties (); 1496 1497 Range range; 1498 if (!metadata.TryGetPropertiesRange (type, out range)) 1499 return false; 1500 1501 return range.Length > 0; 1502 } 1503 ReadProperties(TypeDefinition type)1504 public Collection<PropertyDefinition> ReadProperties (TypeDefinition type) 1505 { 1506 InitializeProperties (); 1507 1508 Range range; 1509 1510 if (!metadata.TryGetPropertiesRange (type, out range)) 1511 return new MemberDefinitionCollection<PropertyDefinition> (type); 1512 1513 metadata.RemovePropertiesRange (type); 1514 1515 var properties = new MemberDefinitionCollection<PropertyDefinition> (type, (int) range.Length); 1516 1517 if (range.Length == 0) 1518 return properties; 1519 1520 this.context = type; 1521 1522 if (!MoveTo (Table.PropertyPtr, range.Start)) { 1523 if (!MoveTo (Table.Property, range.Start)) 1524 return properties; 1525 for (uint i = 0; i < range.Length; i++) 1526 ReadProperty (range.Start + i, properties); 1527 } else 1528 ReadPointers (Table.PropertyPtr, Table.Property, range, properties, ReadProperty); 1529 1530 return properties; 1531 } 1532 ReadProperty(uint property_rid, Collection<PropertyDefinition> properties)1533 void ReadProperty (uint property_rid, Collection<PropertyDefinition> properties) 1534 { 1535 var attributes = (PropertyAttributes) ReadUInt16 (); 1536 var name = ReadString (); 1537 var signature = ReadBlobIndex (); 1538 1539 var reader = ReadSignature (signature); 1540 const byte property_signature = 0x8; 1541 1542 var calling_convention = reader.ReadByte (); 1543 1544 if ((calling_convention & property_signature) == 0) 1545 throw new NotSupportedException (); 1546 1547 var has_this = (calling_convention & 0x20) != 0; 1548 1549 reader.ReadCompressedUInt32 (); // count 1550 1551 var property = new PropertyDefinition (name, attributes, reader.ReadTypeSignature ()); 1552 property.HasThis = has_this; 1553 property.token = new MetadataToken (TokenType.Property, property_rid); 1554 1555 if (IsDeleted (property)) 1556 return; 1557 1558 properties.Add (property); 1559 } 1560 InitializeProperties()1561 void InitializeProperties () 1562 { 1563 if (metadata.Properties != null) 1564 return; 1565 1566 int length = MoveTo (Table.PropertyMap); 1567 1568 metadata.Properties = new Dictionary<uint, Range> (length); 1569 1570 for (uint i = 1; i <= length; i++) { 1571 var type_rid = ReadTableIndex (Table.TypeDef); 1572 var properties_range = ReadListRange (i, Table.PropertyMap, Table.Property); 1573 metadata.AddPropertiesRange (type_rid, properties_range); 1574 } 1575 } 1576 ReadMethodSemantics(MethodDefinition method)1577 MethodSemanticsAttributes ReadMethodSemantics (MethodDefinition method) 1578 { 1579 InitializeMethodSemantics (); 1580 Row<MethodSemanticsAttributes, MetadataToken> row; 1581 if (!metadata.Semantics.TryGetValue (method.token.RID, out row)) 1582 return MethodSemanticsAttributes.None; 1583 1584 var type = method.DeclaringType; 1585 1586 switch (row.Col1) { 1587 case MethodSemanticsAttributes.AddOn: 1588 GetEvent (type, row.Col2).add_method = method; 1589 break; 1590 case MethodSemanticsAttributes.Fire: 1591 GetEvent (type, row.Col2).invoke_method = method; 1592 break; 1593 case MethodSemanticsAttributes.RemoveOn: 1594 GetEvent (type, row.Col2).remove_method = method; 1595 break; 1596 case MethodSemanticsAttributes.Getter: 1597 GetProperty (type, row.Col2).get_method = method; 1598 break; 1599 case MethodSemanticsAttributes.Setter: 1600 GetProperty (type, row.Col2).set_method = method; 1601 break; 1602 case MethodSemanticsAttributes.Other: 1603 switch (row.Col2.TokenType) { 1604 case TokenType.Event: { 1605 var @event = GetEvent (type, row.Col2); 1606 if (@event.other_methods == null) 1607 @event.other_methods = new Collection<MethodDefinition> (); 1608 1609 @event.other_methods.Add (method); 1610 break; 1611 } 1612 case TokenType.Property: { 1613 var property = GetProperty (type, row.Col2); 1614 if (property.other_methods == null) 1615 property.other_methods = new Collection<MethodDefinition> (); 1616 1617 property.other_methods.Add (method); 1618 1619 break; 1620 } 1621 default: 1622 throw new NotSupportedException (); 1623 } 1624 break; 1625 default: 1626 throw new NotSupportedException (); 1627 } 1628 1629 metadata.Semantics.Remove (method.token.RID); 1630 1631 return row.Col1; 1632 } 1633 GetEvent(TypeDefinition type, MetadataToken token)1634 static EventDefinition GetEvent (TypeDefinition type, MetadataToken token) 1635 { 1636 if (token.TokenType != TokenType.Event) 1637 throw new ArgumentException (); 1638 1639 return GetMember (type.Events, token); 1640 } 1641 GetProperty(TypeDefinition type, MetadataToken token)1642 static PropertyDefinition GetProperty (TypeDefinition type, MetadataToken token) 1643 { 1644 if (token.TokenType != TokenType.Property) 1645 throw new ArgumentException (); 1646 1647 return GetMember (type.Properties, token); 1648 } 1649 1650 static TMember GetMember<TMember> (Collection<TMember> members, MetadataToken token) where TMember : IMemberDefinition 1651 { 1652 for (int i = 0; i < members.Count; i++) { 1653 var member = members [i]; 1654 if (member.MetadataToken == token) 1655 return member; 1656 } 1657 1658 throw new ArgumentException (); 1659 } 1660 InitializeMethodSemantics()1661 void InitializeMethodSemantics () 1662 { 1663 if (metadata.Semantics != null) 1664 return; 1665 1666 int length = MoveTo (Table.MethodSemantics); 1667 1668 var semantics = metadata.Semantics = new Dictionary<uint, Row<MethodSemanticsAttributes, MetadataToken>> (0); 1669 1670 for (uint i = 0; i < length; i++) { 1671 var attributes = (MethodSemanticsAttributes) ReadUInt16 (); 1672 var method_rid = ReadTableIndex (Table.Method); 1673 var association = ReadMetadataToken (CodedIndex.HasSemantics); 1674 1675 semantics [method_rid] = new Row<MethodSemanticsAttributes, MetadataToken> (attributes, association); 1676 } 1677 } 1678 ReadMethods(PropertyDefinition property)1679 public void ReadMethods (PropertyDefinition property) 1680 { 1681 ReadAllSemantics (property.DeclaringType); 1682 } 1683 1684 public void ReadMethods (EventDefinition @event) 1685 { 1686 ReadAllSemantics (@event.DeclaringType); 1687 } 1688 ReadAllSemantics(MethodDefinition method)1689 public void ReadAllSemantics (MethodDefinition method) 1690 { 1691 ReadAllSemantics (method.DeclaringType); 1692 } 1693 ReadAllSemantics(TypeDefinition type)1694 void ReadAllSemantics (TypeDefinition type) 1695 { 1696 var methods = type.Methods; 1697 for (int i = 0; i < methods.Count; i++) { 1698 var method = methods [i]; 1699 if (method.sem_attrs_ready) 1700 continue; 1701 1702 method.sem_attrs = ReadMethodSemantics (method); 1703 method.sem_attrs_ready = true; 1704 } 1705 } 1706 ReadMethods(TypeDefinition type)1707 public Collection<MethodDefinition> ReadMethods (TypeDefinition type) 1708 { 1709 var methods_range = type.methods_range; 1710 if (methods_range.Length == 0) 1711 return new MemberDefinitionCollection<MethodDefinition> (type); 1712 1713 var methods = new MemberDefinitionCollection<MethodDefinition> (type, (int) methods_range.Length); 1714 if (!MoveTo (Table.MethodPtr, methods_range.Start)) { 1715 if (!MoveTo (Table.Method, methods_range.Start)) 1716 return methods; 1717 1718 for (uint i = 0; i < methods_range.Length; i++) 1719 ReadMethod (methods_range.Start + i, methods); 1720 } else 1721 ReadPointers (Table.MethodPtr, Table.Method, methods_range, methods, ReadMethod); 1722 1723 return methods; 1724 } 1725 1726 void ReadPointers<TMember> (Table ptr, Table table, Range range, Collection<TMember> members, Action<uint, Collection<TMember>> reader) 1727 where TMember : IMemberDefinition 1728 { 1729 for (uint i = 0; i < range.Length; i++) { 1730 MoveTo (ptr, range.Start + i); 1731 1732 var rid = ReadTableIndex (table); 1733 MoveTo (table, rid); 1734 1735 reader (rid, members); 1736 } 1737 } 1738 IsDeleted(IMemberDefinition member)1739 static bool IsDeleted (IMemberDefinition member) 1740 { 1741 return member.IsSpecialName && member.Name == "_Deleted"; 1742 } 1743 InitializeMethods()1744 void InitializeMethods () 1745 { 1746 if (metadata.Methods != null) 1747 return; 1748 1749 metadata.Methods = new MethodDefinition [image.GetTableLength (Table.Method)]; 1750 } 1751 ReadMethod(uint method_rid, Collection<MethodDefinition> methods)1752 void ReadMethod (uint method_rid, Collection<MethodDefinition> methods) 1753 { 1754 var method = new MethodDefinition (); 1755 method.rva = ReadUInt32 (); 1756 method.ImplAttributes = (MethodImplAttributes) ReadUInt16 (); 1757 method.Attributes = (MethodAttributes) ReadUInt16 (); 1758 method.Name = ReadString (); 1759 method.token = new MetadataToken (TokenType.Method, method_rid); 1760 1761 if (IsDeleted (method)) 1762 return; 1763 1764 methods.Add (method); // attach method 1765 1766 var signature = ReadBlobIndex (); 1767 var param_range = ReadListRange (method_rid, Table.Method, Table.Param); 1768 1769 this.context = method; 1770 1771 ReadMethodSignature (signature, method); 1772 metadata.AddMethodDefinition (method); 1773 1774 if (param_range.Length != 0) { 1775 var position = base.position; 1776 ReadParameters (method, param_range); 1777 base.position = position; 1778 } 1779 1780 if (module.IsWindowsMetadata ()) 1781 WindowsRuntimeProjections.Project (method); 1782 } 1783 ReadParameters(MethodDefinition method, Range param_range)1784 void ReadParameters (MethodDefinition method, Range param_range) 1785 { 1786 if (!MoveTo (Table.ParamPtr, param_range.Start)) { 1787 if (!MoveTo (Table.Param, param_range.Start)) 1788 return; 1789 1790 for (uint i = 0; i < param_range.Length; i++) 1791 ReadParameter (param_range.Start + i, method); 1792 } else 1793 ReadParameterPointers (method, param_range); 1794 } 1795 ReadParameterPointers(MethodDefinition method, Range range)1796 void ReadParameterPointers (MethodDefinition method, Range range) 1797 { 1798 for (uint i = 0; i < range.Length; i++) { 1799 MoveTo (Table.ParamPtr, range.Start + i); 1800 1801 var rid = ReadTableIndex (Table.Param); 1802 1803 MoveTo (Table.Param, rid); 1804 1805 ReadParameter (rid, method); 1806 } 1807 } 1808 ReadParameter(uint param_rid, MethodDefinition method)1809 void ReadParameter (uint param_rid, MethodDefinition method) 1810 { 1811 var attributes = (ParameterAttributes) ReadUInt16 (); 1812 var sequence = ReadUInt16 (); 1813 var name = ReadString (); 1814 1815 var parameter = sequence == 0 1816 ? method.MethodReturnType.Parameter 1817 : method.Parameters [sequence - 1]; 1818 1819 parameter.token = new MetadataToken (TokenType.Param, param_rid); 1820 parameter.Name = name; 1821 parameter.Attributes = attributes; 1822 } 1823 ReadMethodSignature(uint signature, IMethodSignature method)1824 void ReadMethodSignature (uint signature, IMethodSignature method) 1825 { 1826 var reader = ReadSignature (signature); 1827 reader.ReadMethodSignature (method); 1828 } 1829 ReadPInvokeInfo(MethodDefinition method)1830 public PInvokeInfo ReadPInvokeInfo (MethodDefinition method) 1831 { 1832 InitializePInvokes (); 1833 Row<PInvokeAttributes, uint, uint> row; 1834 1835 var rid = method.token.RID; 1836 1837 if (!metadata.PInvokes.TryGetValue (rid, out row)) 1838 return null; 1839 1840 metadata.PInvokes.Remove (rid); 1841 1842 return new PInvokeInfo ( 1843 row.Col1, 1844 image.StringHeap.Read (row.Col2), 1845 module.ModuleReferences [(int) row.Col3 - 1]); 1846 } 1847 InitializePInvokes()1848 void InitializePInvokes () 1849 { 1850 if (metadata.PInvokes != null) 1851 return; 1852 1853 int length = MoveTo (Table.ImplMap); 1854 1855 var pinvokes = metadata.PInvokes = new Dictionary<uint, Row<PInvokeAttributes, uint, uint>> (length); 1856 1857 for (int i = 1; i <= length; i++) { 1858 var attributes = (PInvokeAttributes) ReadUInt16 (); 1859 var method = ReadMetadataToken (CodedIndex.MemberForwarded); 1860 var name = ReadStringIndex (); 1861 var scope = ReadTableIndex (Table.File); 1862 1863 if (method.TokenType != TokenType.Method) 1864 continue; 1865 1866 pinvokes.Add (method.RID, new Row<PInvokeAttributes, uint, uint> (attributes, name, scope)); 1867 } 1868 } 1869 HasGenericParameters(IGenericParameterProvider provider)1870 public bool HasGenericParameters (IGenericParameterProvider provider) 1871 { 1872 InitializeGenericParameters (); 1873 1874 Range [] ranges; 1875 if (!metadata.TryGetGenericParameterRanges (provider, out ranges)) 1876 return false; 1877 1878 return RangesSize (ranges) > 0; 1879 } 1880 ReadGenericParameters(IGenericParameterProvider provider)1881 public Collection<GenericParameter> ReadGenericParameters (IGenericParameterProvider provider) 1882 { 1883 InitializeGenericParameters (); 1884 1885 Range [] ranges; 1886 if (!metadata.TryGetGenericParameterRanges (provider, out ranges)) 1887 return new GenericParameterCollection (provider); 1888 1889 metadata.RemoveGenericParameterRange (provider); 1890 1891 var generic_parameters = new GenericParameterCollection (provider, RangesSize (ranges)); 1892 1893 for (int i = 0; i < ranges.Length; i++) 1894 ReadGenericParametersRange (ranges [i], provider, generic_parameters); 1895 1896 return generic_parameters; 1897 } 1898 ReadGenericParametersRange(Range range, IGenericParameterProvider provider, GenericParameterCollection generic_parameters)1899 void ReadGenericParametersRange (Range range, IGenericParameterProvider provider, GenericParameterCollection generic_parameters) 1900 { 1901 if (!MoveTo (Table.GenericParam, range.Start)) 1902 return; 1903 1904 for (uint i = 0; i < range.Length; i++) { 1905 ReadUInt16 (); // index 1906 var flags = (GenericParameterAttributes) ReadUInt16 (); 1907 ReadMetadataToken (CodedIndex.TypeOrMethodDef); 1908 var name = ReadString (); 1909 1910 var parameter = new GenericParameter (name, provider); 1911 parameter.token = new MetadataToken (TokenType.GenericParam, range.Start + i); 1912 parameter.Attributes = flags; 1913 1914 generic_parameters.Add (parameter); 1915 } 1916 } 1917 InitializeGenericParameters()1918 void InitializeGenericParameters () 1919 { 1920 if (metadata.GenericParameters != null) 1921 return; 1922 1923 metadata.GenericParameters = InitializeRanges ( 1924 Table.GenericParam, () => { 1925 Advance (4); 1926 var next = ReadMetadataToken (CodedIndex.TypeOrMethodDef); 1927 ReadStringIndex (); 1928 return next; 1929 }); 1930 } 1931 InitializeRanges(Table table, Func<MetadataToken> get_next)1932 Dictionary<MetadataToken, Range []> InitializeRanges (Table table, Func<MetadataToken> get_next) 1933 { 1934 int length = MoveTo (table); 1935 var ranges = new Dictionary<MetadataToken, Range []> (length); 1936 1937 if (length == 0) 1938 return ranges; 1939 1940 MetadataToken owner = MetadataToken.Zero; 1941 Range range = new Range (1, 0); 1942 1943 for (uint i = 1; i <= length; i++) { 1944 var next = get_next (); 1945 1946 if (i == 1) { 1947 owner = next; 1948 range.Length++; 1949 } else if (next != owner) { 1950 AddRange (ranges, owner, range); 1951 range = new Range (i, 1); 1952 owner = next; 1953 } else 1954 range.Length++; 1955 } 1956 1957 AddRange (ranges, owner, range); 1958 1959 return ranges; 1960 } 1961 AddRange(Dictionary<MetadataToken, Range []> ranges, MetadataToken owner, Range range)1962 static void AddRange (Dictionary<MetadataToken, Range []> ranges, MetadataToken owner, Range range) 1963 { 1964 if (owner.RID == 0) 1965 return; 1966 1967 Range [] slots; 1968 if (!ranges.TryGetValue (owner, out slots)) { 1969 ranges.Add (owner, new [] { range }); 1970 return; 1971 } 1972 1973 ranges [owner] = slots.Add(range); 1974 } 1975 HasGenericConstraints(GenericParameter generic_parameter)1976 public bool HasGenericConstraints (GenericParameter generic_parameter) 1977 { 1978 InitializeGenericConstraints (); 1979 1980 Collection<MetadataToken> mapping; 1981 if (!metadata.TryGetGenericConstraintMapping (generic_parameter, out mapping)) 1982 return false; 1983 1984 return mapping.Count > 0; 1985 } 1986 ReadGenericConstraints(GenericParameter generic_parameter)1987 public Collection<TypeReference> ReadGenericConstraints (GenericParameter generic_parameter) 1988 { 1989 InitializeGenericConstraints (); 1990 1991 Collection<MetadataToken> mapping; 1992 if (!metadata.TryGetGenericConstraintMapping (generic_parameter, out mapping)) 1993 return new Collection<TypeReference> (); 1994 1995 var constraints = new Collection<TypeReference> (mapping.Count); 1996 1997 this.context = (IGenericContext) generic_parameter.Owner; 1998 1999 for (int i = 0; i < mapping.Count; i++) 2000 constraints.Add (GetTypeDefOrRef (mapping [i])); 2001 2002 metadata.RemoveGenericConstraintMapping (generic_parameter); 2003 2004 return constraints; 2005 } 2006 InitializeGenericConstraints()2007 void InitializeGenericConstraints () 2008 { 2009 if (metadata.GenericConstraints != null) 2010 return; 2011 2012 var length = MoveTo (Table.GenericParamConstraint); 2013 2014 metadata.GenericConstraints = new Dictionary<uint, Collection<MetadataToken>> (length); 2015 2016 for (int i = 1; i <= length; i++) 2017 AddGenericConstraintMapping ( 2018 ReadTableIndex (Table.GenericParam), 2019 ReadMetadataToken (CodedIndex.TypeDefOrRef)); 2020 } 2021 AddGenericConstraintMapping(uint generic_parameter, MetadataToken constraint)2022 void AddGenericConstraintMapping (uint generic_parameter, MetadataToken constraint) 2023 { 2024 metadata.SetGenericConstraintMapping ( 2025 generic_parameter, 2026 AddMapping (metadata.GenericConstraints, generic_parameter, constraint)); 2027 } 2028 HasOverrides(MethodDefinition method)2029 public bool HasOverrides (MethodDefinition method) 2030 { 2031 InitializeOverrides (); 2032 Collection<MetadataToken> mapping; 2033 2034 if (!metadata.TryGetOverrideMapping (method, out mapping)) 2035 return false; 2036 2037 return mapping.Count > 0; 2038 } 2039 ReadOverrides(MethodDefinition method)2040 public Collection<MethodReference> ReadOverrides (MethodDefinition method) 2041 { 2042 InitializeOverrides (); 2043 2044 Collection<MetadataToken> mapping; 2045 if (!metadata.TryGetOverrideMapping (method, out mapping)) 2046 return new Collection<MethodReference> (); 2047 2048 var overrides = new Collection<MethodReference> (mapping.Count); 2049 2050 this.context = method; 2051 2052 for (int i = 0; i < mapping.Count; i++) 2053 overrides.Add ((MethodReference) LookupToken (mapping [i])); 2054 2055 metadata.RemoveOverrideMapping (method); 2056 2057 return overrides; 2058 } 2059 InitializeOverrides()2060 void InitializeOverrides () 2061 { 2062 if (metadata.Overrides != null) 2063 return; 2064 2065 var length = MoveTo (Table.MethodImpl); 2066 2067 metadata.Overrides = new Dictionary<uint, Collection<MetadataToken>> (length); 2068 2069 for (int i = 1; i <= length; i++) { 2070 ReadTableIndex (Table.TypeDef); 2071 2072 var method = ReadMetadataToken (CodedIndex.MethodDefOrRef); 2073 if (method.TokenType != TokenType.Method) 2074 throw new NotSupportedException (); 2075 2076 var @override = ReadMetadataToken (CodedIndex.MethodDefOrRef); 2077 2078 AddOverrideMapping (method.RID, @override); 2079 } 2080 } 2081 AddOverrideMapping(uint method_rid, MetadataToken @override)2082 void AddOverrideMapping (uint method_rid, MetadataToken @override) 2083 { 2084 metadata.SetOverrideMapping ( 2085 method_rid, 2086 AddMapping (metadata.Overrides, method_rid, @override)); 2087 } 2088 ReadMethodBody(MethodDefinition method)2089 public MethodBody ReadMethodBody (MethodDefinition method) 2090 { 2091 return code.ReadMethodBody (method); 2092 } 2093 ReadCodeSize(MethodDefinition method)2094 public int ReadCodeSize (MethodDefinition method) 2095 { 2096 return code.ReadCodeSize (method); 2097 } 2098 ReadCallSite(MetadataToken token)2099 public CallSite ReadCallSite (MetadataToken token) 2100 { 2101 if (!MoveTo (Table.StandAloneSig, token.RID)) 2102 return null; 2103 2104 var signature = ReadBlobIndex (); 2105 2106 var call_site = new CallSite (); 2107 2108 ReadMethodSignature (signature, call_site); 2109 2110 call_site.MetadataToken = token; 2111 2112 return call_site; 2113 } 2114 ReadVariables(MetadataToken local_var_token)2115 public VariableDefinitionCollection ReadVariables (MetadataToken local_var_token) 2116 { 2117 if (!MoveTo (Table.StandAloneSig, local_var_token.RID)) 2118 return null; 2119 2120 var reader = ReadSignature (ReadBlobIndex ()); 2121 const byte local_sig = 0x7; 2122 2123 if (reader.ReadByte () != local_sig) 2124 throw new NotSupportedException (); 2125 2126 var count = reader.ReadCompressedUInt32 (); 2127 if (count == 0) 2128 return null; 2129 2130 var variables = new VariableDefinitionCollection ((int) count); 2131 2132 for (int i = 0; i < count; i++) 2133 variables.Add (new VariableDefinition (reader.ReadTypeSignature ())); 2134 2135 return variables; 2136 } 2137 LookupToken(MetadataToken token)2138 public IMetadataTokenProvider LookupToken (MetadataToken token) 2139 { 2140 var rid = token.RID; 2141 2142 if (rid == 0) 2143 return null; 2144 2145 if (metadata_reader != null) 2146 return metadata_reader.LookupToken (token); 2147 2148 IMetadataTokenProvider element; 2149 var position = this.position; 2150 var context = this.context; 2151 2152 switch (token.TokenType) { 2153 case TokenType.TypeDef: 2154 element = GetTypeDefinition (rid); 2155 break; 2156 case TokenType.TypeRef: 2157 element = GetTypeReference (rid); 2158 break; 2159 case TokenType.TypeSpec: 2160 element = GetTypeSpecification (rid); 2161 break; 2162 case TokenType.Field: 2163 element = GetFieldDefinition (rid); 2164 break; 2165 case TokenType.Method: 2166 element = GetMethodDefinition (rid); 2167 break; 2168 case TokenType.MemberRef: 2169 element = GetMemberReference (rid); 2170 break; 2171 case TokenType.MethodSpec: 2172 element = GetMethodSpecification (rid); 2173 break; 2174 default: 2175 return null; 2176 } 2177 2178 this.position = position; 2179 this.context = context; 2180 2181 return element; 2182 } 2183 GetFieldDefinition(uint rid)2184 public FieldDefinition GetFieldDefinition (uint rid) 2185 { 2186 InitializeTypeDefinitions (); 2187 2188 var field = metadata.GetFieldDefinition (rid); 2189 if (field != null) 2190 return field; 2191 2192 return LookupField (rid); 2193 } 2194 LookupField(uint rid)2195 FieldDefinition LookupField (uint rid) 2196 { 2197 var type = metadata.GetFieldDeclaringType (rid); 2198 if (type == null) 2199 return null; 2200 2201 Mixin.Read (type.Fields); 2202 2203 return metadata.GetFieldDefinition (rid); 2204 } 2205 GetMethodDefinition(uint rid)2206 public MethodDefinition GetMethodDefinition (uint rid) 2207 { 2208 InitializeTypeDefinitions (); 2209 2210 var method = metadata.GetMethodDefinition (rid); 2211 if (method != null) 2212 return method; 2213 2214 return LookupMethod (rid); 2215 } 2216 LookupMethod(uint rid)2217 MethodDefinition LookupMethod (uint rid) 2218 { 2219 var type = metadata.GetMethodDeclaringType (rid); 2220 if (type == null) 2221 return null; 2222 2223 Mixin.Read (type.Methods); 2224 2225 return metadata.GetMethodDefinition (rid); 2226 } 2227 GetMethodSpecification(uint rid)2228 MethodSpecification GetMethodSpecification (uint rid) 2229 { 2230 if (!MoveTo (Table.MethodSpec, rid)) 2231 return null; 2232 2233 var element_method = (MethodReference) LookupToken ( 2234 ReadMetadataToken (CodedIndex.MethodDefOrRef)); 2235 var signature = ReadBlobIndex (); 2236 2237 var method_spec = ReadMethodSpecSignature (signature, element_method); 2238 method_spec.token = new MetadataToken (TokenType.MethodSpec, rid); 2239 return method_spec; 2240 } 2241 ReadMethodSpecSignature(uint signature, MethodReference method)2242 MethodSpecification ReadMethodSpecSignature (uint signature, MethodReference method) 2243 { 2244 var reader = ReadSignature (signature); 2245 const byte methodspec_sig = 0x0a; 2246 2247 var call_conv = reader.ReadByte (); 2248 2249 if (call_conv != methodspec_sig) 2250 throw new NotSupportedException (); 2251 2252 var instance = new GenericInstanceMethod (method); 2253 2254 reader.ReadGenericInstanceSignature (method, instance); 2255 2256 return instance; 2257 } 2258 GetMemberReference(uint rid)2259 MemberReference GetMemberReference (uint rid) 2260 { 2261 InitializeMemberReferences (); 2262 2263 var member = metadata.GetMemberReference (rid); 2264 if (member != null) 2265 return member; 2266 2267 member = ReadMemberReference (rid); 2268 if (member != null && !member.ContainsGenericParameter) 2269 metadata.AddMemberReference (member); 2270 return member; 2271 } 2272 ReadMemberReference(uint rid)2273 MemberReference ReadMemberReference (uint rid) 2274 { 2275 if (!MoveTo (Table.MemberRef, rid)) 2276 return null; 2277 2278 var token = ReadMetadataToken (CodedIndex.MemberRefParent); 2279 var name = ReadString (); 2280 var signature = ReadBlobIndex (); 2281 2282 MemberReference member; 2283 2284 switch (token.TokenType) { 2285 case TokenType.TypeDef: 2286 case TokenType.TypeRef: 2287 case TokenType.TypeSpec: 2288 member = ReadTypeMemberReference (token, name, signature); 2289 break; 2290 case TokenType.Method: 2291 member = ReadMethodMemberReference (token, name, signature); 2292 break; 2293 default: 2294 throw new NotSupportedException (); 2295 } 2296 2297 member.token = new MetadataToken (TokenType.MemberRef, rid); 2298 2299 if (module.IsWindowsMetadata ()) 2300 WindowsRuntimeProjections.Project (member); 2301 2302 return member; 2303 } 2304 ReadTypeMemberReference(MetadataToken type, string name, uint signature)2305 MemberReference ReadTypeMemberReference (MetadataToken type, string name, uint signature) 2306 { 2307 var declaring_type = GetTypeDefOrRef (type); 2308 2309 if (!declaring_type.IsArray) 2310 this.context = declaring_type; 2311 2312 var member = ReadMemberReferenceSignature (signature, declaring_type); 2313 member.Name = name; 2314 2315 return member; 2316 } 2317 ReadMemberReferenceSignature(uint signature, TypeReference declaring_type)2318 MemberReference ReadMemberReferenceSignature (uint signature, TypeReference declaring_type) 2319 { 2320 var reader = ReadSignature (signature); 2321 const byte field_sig = 0x6; 2322 2323 if (reader.buffer [reader.position] == field_sig) { 2324 reader.position++; 2325 var field = new FieldReference (); 2326 field.DeclaringType = declaring_type; 2327 field.FieldType = reader.ReadTypeSignature (); 2328 return field; 2329 } else { 2330 var method = new MethodReference (); 2331 method.DeclaringType = declaring_type; 2332 reader.ReadMethodSignature (method); 2333 return method; 2334 } 2335 } 2336 ReadMethodMemberReference(MetadataToken token, string name, uint signature)2337 MemberReference ReadMethodMemberReference (MetadataToken token, string name, uint signature) 2338 { 2339 var method = GetMethodDefinition (token.RID); 2340 2341 this.context = method; 2342 2343 var member = ReadMemberReferenceSignature (signature, method.DeclaringType); 2344 member.Name = name; 2345 2346 return member; 2347 } 2348 InitializeMemberReferences()2349 void InitializeMemberReferences () 2350 { 2351 if (metadata.MemberReferences != null) 2352 return; 2353 2354 metadata.MemberReferences = new MemberReference [image.GetTableLength (Table.MemberRef)]; 2355 } 2356 GetMemberReferences()2357 public IEnumerable<MemberReference> GetMemberReferences () 2358 { 2359 InitializeMemberReferences (); 2360 2361 var length = image.GetTableLength (Table.MemberRef); 2362 2363 var type_system = module.TypeSystem; 2364 2365 var context = new MethodDefinition (string.Empty, MethodAttributes.Static, type_system.Void); 2366 context.DeclaringType = new TypeDefinition (string.Empty, string.Empty, TypeAttributes.Public); 2367 2368 var member_references = new MemberReference [length]; 2369 2370 for (uint i = 1; i <= length; i++) { 2371 this.context = context; 2372 member_references [i - 1] = GetMemberReference (i); 2373 } 2374 2375 return member_references; 2376 } 2377 InitializeConstants()2378 void InitializeConstants () 2379 { 2380 if (metadata.Constants != null) 2381 return; 2382 2383 var length = MoveTo (Table.Constant); 2384 2385 var constants = metadata.Constants = new Dictionary<MetadataToken, Row<ElementType, uint>> (length); 2386 2387 for (uint i = 1; i <= length; i++) { 2388 var type = (ElementType) ReadUInt16 (); 2389 var owner = ReadMetadataToken (CodedIndex.HasConstant); 2390 var signature = ReadBlobIndex (); 2391 2392 constants.Add (owner, new Row<ElementType, uint> (type, signature)); 2393 } 2394 } 2395 ReadConstantSignature(MetadataToken token)2396 public TypeReference ReadConstantSignature (MetadataToken token) 2397 { 2398 if (token.TokenType != TokenType.Signature) 2399 throw new NotSupportedException (); 2400 2401 if (!MoveTo (Table.StandAloneSig, token.RID)) 2402 return null; 2403 2404 return ReadFieldType (ReadBlobIndex ()); 2405 } 2406 ReadConstant(IConstantProvider owner)2407 public object ReadConstant (IConstantProvider owner) 2408 { 2409 InitializeConstants (); 2410 2411 Row<ElementType, uint> row; 2412 if (!metadata.Constants.TryGetValue (owner.MetadataToken, out row)) 2413 return Mixin.NoValue; 2414 2415 metadata.Constants.Remove (owner.MetadataToken); 2416 2417 return ReadConstantValue (row.Col1, row.Col2); 2418 } 2419 ReadConstantValue(ElementType etype, uint signature)2420 object ReadConstantValue (ElementType etype, uint signature) 2421 { 2422 switch (etype) { 2423 case ElementType.Class: 2424 case ElementType.Object: 2425 return null; 2426 case ElementType.String: 2427 return ReadConstantString (signature); 2428 default: 2429 return ReadConstantPrimitive (etype, signature); 2430 } 2431 } 2432 ReadConstantString(uint signature)2433 string ReadConstantString (uint signature) 2434 { 2435 byte [] blob; 2436 int index, count; 2437 2438 GetBlobView (signature, out blob, out index, out count); 2439 if (count == 0) 2440 return string.Empty; 2441 2442 if ((count & 1) == 1) 2443 count--; 2444 2445 return Encoding.Unicode.GetString (blob, index, count); 2446 } 2447 ReadConstantPrimitive(ElementType type, uint signature)2448 object ReadConstantPrimitive (ElementType type, uint signature) 2449 { 2450 var reader = ReadSignature (signature); 2451 return reader.ReadConstantSignature (type); 2452 } 2453 InitializeCustomAttributes()2454 internal void InitializeCustomAttributes () 2455 { 2456 if (metadata.CustomAttributes != null) 2457 return; 2458 2459 metadata.CustomAttributes = InitializeRanges ( 2460 Table.CustomAttribute, () => { 2461 var next = ReadMetadataToken (CodedIndex.HasCustomAttribute); 2462 ReadMetadataToken (CodedIndex.CustomAttributeType); 2463 ReadBlobIndex (); 2464 return next; 2465 }); 2466 } 2467 HasCustomAttributes(ICustomAttributeProvider owner)2468 public bool HasCustomAttributes (ICustomAttributeProvider owner) 2469 { 2470 InitializeCustomAttributes (); 2471 2472 Range [] ranges; 2473 if (!metadata.TryGetCustomAttributeRanges (owner, out ranges)) 2474 return false; 2475 2476 return RangesSize (ranges) > 0; 2477 } 2478 ReadCustomAttributes(ICustomAttributeProvider owner)2479 public Collection<CustomAttribute> ReadCustomAttributes (ICustomAttributeProvider owner) 2480 { 2481 InitializeCustomAttributes (); 2482 2483 Range [] ranges; 2484 if (!metadata.TryGetCustomAttributeRanges (owner, out ranges)) 2485 return new Collection<CustomAttribute> (); 2486 2487 var custom_attributes = new Collection<CustomAttribute> (RangesSize (ranges)); 2488 2489 for (int i = 0; i < ranges.Length; i++) 2490 ReadCustomAttributeRange (ranges [i], custom_attributes); 2491 2492 metadata.RemoveCustomAttributeRange (owner); 2493 2494 if (module.IsWindowsMetadata ()) 2495 foreach (var custom_attribute in custom_attributes) 2496 WindowsRuntimeProjections.Project (owner, custom_attribute); 2497 2498 return custom_attributes; 2499 } 2500 ReadCustomAttributeRange(Range range, Collection<CustomAttribute> custom_attributes)2501 void ReadCustomAttributeRange (Range range, Collection<CustomAttribute> custom_attributes) 2502 { 2503 if (!MoveTo (Table.CustomAttribute, range.Start)) 2504 return; 2505 2506 for (var i = 0; i < range.Length; i++) { 2507 ReadMetadataToken (CodedIndex.HasCustomAttribute); 2508 2509 var constructor = (MethodReference) LookupToken ( 2510 ReadMetadataToken (CodedIndex.CustomAttributeType)); 2511 2512 var signature = ReadBlobIndex (); 2513 2514 custom_attributes.Add (new CustomAttribute (signature, constructor)); 2515 } 2516 } 2517 RangesSize(Range [] ranges)2518 static int RangesSize (Range [] ranges) 2519 { 2520 uint size = 0; 2521 for (int i = 0; i < ranges.Length; i++) 2522 size += ranges [i].Length; 2523 2524 return (int) size; 2525 } 2526 GetCustomAttributes()2527 public IEnumerable<CustomAttribute> GetCustomAttributes () 2528 { 2529 InitializeTypeDefinitions (); 2530 2531 var length = image.TableHeap [Table.CustomAttribute].Length; 2532 var custom_attributes = new Collection<CustomAttribute> ((int) length); 2533 ReadCustomAttributeRange (new Range (1, length), custom_attributes); 2534 2535 return custom_attributes; 2536 } 2537 ReadCustomAttributeBlob(uint signature)2538 public byte [] ReadCustomAttributeBlob (uint signature) 2539 { 2540 return ReadBlob (signature); 2541 } 2542 ReadCustomAttributeSignature(CustomAttribute attribute)2543 public void ReadCustomAttributeSignature (CustomAttribute attribute) 2544 { 2545 var reader = ReadSignature (attribute.signature); 2546 2547 if (!reader.CanReadMore ()) 2548 return; 2549 2550 if (reader.ReadUInt16 () != 0x0001) 2551 throw new InvalidOperationException (); 2552 2553 var constructor = attribute.Constructor; 2554 if (constructor.HasParameters) 2555 reader.ReadCustomAttributeConstructorArguments (attribute, constructor.Parameters); 2556 2557 if (!reader.CanReadMore ()) 2558 return; 2559 2560 var named = reader.ReadUInt16 (); 2561 2562 if (named == 0) 2563 return; 2564 2565 reader.ReadCustomAttributeNamedArguments (named, ref attribute.fields, ref attribute.properties); 2566 } 2567 InitializeMarshalInfos()2568 void InitializeMarshalInfos () 2569 { 2570 if (metadata.FieldMarshals != null) 2571 return; 2572 2573 var length = MoveTo (Table.FieldMarshal); 2574 2575 var marshals = metadata.FieldMarshals = new Dictionary<MetadataToken, uint> (length); 2576 2577 for (int i = 0; i < length; i++) { 2578 var token = ReadMetadataToken (CodedIndex.HasFieldMarshal); 2579 var signature = ReadBlobIndex (); 2580 if (token.RID == 0) 2581 continue; 2582 2583 marshals.Add (token, signature); 2584 } 2585 } 2586 HasMarshalInfo(IMarshalInfoProvider owner)2587 public bool HasMarshalInfo (IMarshalInfoProvider owner) 2588 { 2589 InitializeMarshalInfos (); 2590 2591 return metadata.FieldMarshals.ContainsKey (owner.MetadataToken); 2592 } 2593 ReadMarshalInfo(IMarshalInfoProvider owner)2594 public MarshalInfo ReadMarshalInfo (IMarshalInfoProvider owner) 2595 { 2596 InitializeMarshalInfos (); 2597 2598 uint signature; 2599 if (!metadata.FieldMarshals.TryGetValue (owner.MetadataToken, out signature)) 2600 return null; 2601 2602 var reader = ReadSignature (signature); 2603 2604 metadata.FieldMarshals.Remove (owner.MetadataToken); 2605 2606 return reader.ReadMarshalInfo (); 2607 } 2608 InitializeSecurityDeclarations()2609 void InitializeSecurityDeclarations () 2610 { 2611 if (metadata.SecurityDeclarations != null) 2612 return; 2613 2614 metadata.SecurityDeclarations = InitializeRanges ( 2615 Table.DeclSecurity, () => { 2616 ReadUInt16 (); 2617 var next = ReadMetadataToken (CodedIndex.HasDeclSecurity); 2618 ReadBlobIndex (); 2619 return next; 2620 }); 2621 } 2622 HasSecurityDeclarations(ISecurityDeclarationProvider owner)2623 public bool HasSecurityDeclarations (ISecurityDeclarationProvider owner) 2624 { 2625 InitializeSecurityDeclarations (); 2626 2627 Range [] ranges; 2628 if (!metadata.TryGetSecurityDeclarationRanges (owner, out ranges)) 2629 return false; 2630 2631 return RangesSize (ranges) > 0; 2632 } 2633 ReadSecurityDeclarations(ISecurityDeclarationProvider owner)2634 public Collection<SecurityDeclaration> ReadSecurityDeclarations (ISecurityDeclarationProvider owner) 2635 { 2636 InitializeSecurityDeclarations (); 2637 2638 Range [] ranges; 2639 if (!metadata.TryGetSecurityDeclarationRanges (owner, out ranges)) 2640 return new Collection<SecurityDeclaration> (); 2641 2642 var security_declarations = new Collection<SecurityDeclaration> (RangesSize (ranges)); 2643 2644 for (int i = 0; i < ranges.Length; i++) 2645 ReadSecurityDeclarationRange (ranges [i], security_declarations); 2646 2647 metadata.RemoveSecurityDeclarationRange (owner); 2648 2649 return security_declarations; 2650 } 2651 ReadSecurityDeclarationRange(Range range, Collection<SecurityDeclaration> security_declarations)2652 void ReadSecurityDeclarationRange (Range range, Collection<SecurityDeclaration> security_declarations) 2653 { 2654 if (!MoveTo (Table.DeclSecurity, range.Start)) 2655 return; 2656 2657 for (int i = 0; i < range.Length; i++) { 2658 var action = (SecurityAction) ReadUInt16 (); 2659 ReadMetadataToken (CodedIndex.HasDeclSecurity); 2660 var signature = ReadBlobIndex (); 2661 2662 security_declarations.Add (new SecurityDeclaration (action, signature, module)); 2663 } 2664 } 2665 ReadSecurityDeclarationBlob(uint signature)2666 public byte [] ReadSecurityDeclarationBlob (uint signature) 2667 { 2668 return ReadBlob (signature); 2669 } 2670 ReadSecurityDeclarationSignature(SecurityDeclaration declaration)2671 public void ReadSecurityDeclarationSignature (SecurityDeclaration declaration) 2672 { 2673 var signature = declaration.signature; 2674 var reader = ReadSignature (signature); 2675 2676 if (reader.buffer [reader.position] != '.') { 2677 ReadXmlSecurityDeclaration (signature, declaration); 2678 return; 2679 } 2680 2681 reader.position++; 2682 var count = reader.ReadCompressedUInt32 (); 2683 var attributes = new Collection<SecurityAttribute> ((int) count); 2684 2685 for (int i = 0; i < count; i++) 2686 attributes.Add (reader.ReadSecurityAttribute ()); 2687 2688 declaration.security_attributes = attributes; 2689 } 2690 ReadXmlSecurityDeclaration(uint signature, SecurityDeclaration declaration)2691 void ReadXmlSecurityDeclaration (uint signature, SecurityDeclaration declaration) 2692 { 2693 var attributes = new Collection<SecurityAttribute> (1); 2694 2695 var attribute = new SecurityAttribute ( 2696 module.TypeSystem.LookupType ("System.Security.Permissions", "PermissionSetAttribute")); 2697 2698 attribute.properties = new Collection<CustomAttributeNamedArgument> (1); 2699 attribute.properties.Add ( 2700 new CustomAttributeNamedArgument ( 2701 "XML", 2702 new CustomAttributeArgument ( 2703 module.TypeSystem.String, 2704 ReadUnicodeStringBlob (signature)))); 2705 2706 attributes.Add (attribute); 2707 2708 declaration.security_attributes = attributes; 2709 } 2710 ReadExportedTypes()2711 public Collection<ExportedType> ReadExportedTypes () 2712 { 2713 var length = MoveTo (Table.ExportedType); 2714 if (length == 0) 2715 return new Collection<ExportedType> (); 2716 2717 var exported_types = new Collection<ExportedType> (length); 2718 2719 for (int i = 1; i <= length; i++) { 2720 var attributes = (TypeAttributes) ReadUInt32 (); 2721 var identifier = ReadUInt32 (); 2722 var name = ReadString (); 2723 var @namespace = ReadString (); 2724 var implementation = ReadMetadataToken (CodedIndex.Implementation); 2725 2726 ExportedType declaring_type = null; 2727 IMetadataScope scope = null; 2728 2729 switch (implementation.TokenType) { 2730 case TokenType.AssemblyRef: 2731 case TokenType.File: 2732 scope = GetExportedTypeScope (implementation); 2733 break; 2734 case TokenType.ExportedType: 2735 // FIXME: if the table is not properly sorted 2736 declaring_type = exported_types [(int) implementation.RID - 1]; 2737 break; 2738 } 2739 2740 var exported_type = new ExportedType (@namespace, name, module, scope) { 2741 Attributes = attributes, 2742 Identifier = (int) identifier, 2743 DeclaringType = declaring_type, 2744 }; 2745 exported_type.token = new MetadataToken (TokenType.ExportedType, i); 2746 2747 exported_types.Add (exported_type); 2748 } 2749 2750 return exported_types; 2751 } 2752 GetExportedTypeScope(MetadataToken token)2753 IMetadataScope GetExportedTypeScope (MetadataToken token) 2754 { 2755 var position = this.position; 2756 IMetadataScope scope; 2757 2758 switch (token.TokenType) { 2759 case TokenType.AssemblyRef: 2760 InitializeAssemblyReferences (); 2761 scope = metadata.GetAssemblyNameReference (token.RID); 2762 break; 2763 case TokenType.File: 2764 InitializeModuleReferences (); 2765 scope = GetModuleReferenceFromFile (token); 2766 break; 2767 default: 2768 throw new NotSupportedException (); 2769 } 2770 2771 this.position = position; 2772 return scope; 2773 } 2774 GetModuleReferenceFromFile(MetadataToken token)2775 ModuleReference GetModuleReferenceFromFile (MetadataToken token) 2776 { 2777 if (!MoveTo (Table.File, token.RID)) 2778 return null; 2779 2780 ReadUInt32 (); 2781 var file_name = ReadString (); 2782 var modules = module.ModuleReferences; 2783 2784 ModuleReference reference; 2785 for (int i = 0; i < modules.Count; i++) { 2786 reference = modules [i]; 2787 if (reference.Name == file_name) 2788 return reference; 2789 } 2790 2791 reference = new ModuleReference (file_name); 2792 modules.Add (reference); 2793 return reference; 2794 } 2795 InitializeDocuments()2796 void InitializeDocuments () 2797 { 2798 if (metadata.Documents != null) 2799 return; 2800 2801 int length = MoveTo (Table.Document); 2802 2803 var documents = metadata.Documents = new Document [length]; 2804 2805 for (uint i = 1; i <= length; i++) { 2806 var name_index = ReadBlobIndex (); 2807 var hash_algorithm = ReadGuid (); 2808 var hash = ReadBlob (); 2809 var language = ReadGuid (); 2810 2811 var signature = ReadSignature (name_index); 2812 var name = signature.ReadDocumentName (); 2813 2814 documents [i - 1] = new Document (name) { 2815 HashAlgorithm = hash_algorithm.ToHashAlgorithm (), 2816 Hash = hash, 2817 Language = language.ToLanguage (), 2818 token = new MetadataToken (TokenType.Document, i), 2819 }; 2820 } 2821 } 2822 ReadSequencePoints(MethodDefinition method)2823 public Collection<SequencePoint> ReadSequencePoints (MethodDefinition method) 2824 { 2825 InitializeDocuments (); 2826 2827 if (!MoveTo (Table.MethodDebugInformation, method.MetadataToken.RID)) 2828 return new Collection<SequencePoint> (0); 2829 2830 var document_index = ReadTableIndex (Table.Document); 2831 var signature = ReadBlobIndex (); 2832 if (signature == 0) 2833 return new Collection<SequencePoint> (0); 2834 2835 var document = GetDocument (document_index); 2836 var reader = ReadSignature (signature); 2837 2838 return reader.ReadSequencePoints (document); 2839 } 2840 GetDocument(uint rid)2841 public Document GetDocument (uint rid) 2842 { 2843 var document = metadata.GetDocument (rid); 2844 if (document == null) 2845 return null; 2846 2847 document.custom_infos = GetCustomDebugInformation (document); 2848 return document; 2849 } 2850 InitializeLocalScopes()2851 void InitializeLocalScopes () 2852 { 2853 if (metadata.LocalScopes != null) 2854 return; 2855 2856 InitializeMethods (); 2857 2858 int length = MoveTo (Table.LocalScope); 2859 2860 metadata.LocalScopes = new Dictionary<uint, Collection<Row<uint, Range, Range, uint, uint, uint>>> (); 2861 2862 for (uint i = 1; i <= length; i++) { 2863 var method = ReadTableIndex (Table.Method); 2864 var import = ReadTableIndex (Table.ImportScope); 2865 var variables = ReadListRange (i, Table.LocalScope, Table.LocalVariable); 2866 var constants = ReadListRange (i, Table.LocalScope, Table.LocalConstant); 2867 var scope_start = ReadUInt32 (); 2868 var scope_length = ReadUInt32 (); 2869 2870 metadata.SetLocalScopes (method, AddMapping (metadata.LocalScopes, method, new Row<uint, Range, Range, uint, uint, uint> (import, variables, constants, scope_start, scope_length, i))); 2871 } 2872 } 2873 ReadScope(MethodDefinition method)2874 public ScopeDebugInformation ReadScope (MethodDefinition method) 2875 { 2876 InitializeLocalScopes (); 2877 InitializeImportScopes (); 2878 2879 Collection<Row<uint, Range, Range, uint, uint, uint>> records; 2880 if (!metadata.TryGetLocalScopes (method, out records)) 2881 return null; 2882 2883 var method_scope = null as ScopeDebugInformation; 2884 2885 for (int i = 0; i < records.Count; i++) { 2886 var scope = ReadLocalScope (records [i]); 2887 2888 if (i == 0) { 2889 method_scope = scope; 2890 continue; 2891 } 2892 2893 if (!AddScope (method_scope.scopes, scope)) 2894 method_scope.Scopes.Add (scope); 2895 } 2896 2897 return method_scope; 2898 } 2899 AddScope(Collection<ScopeDebugInformation> scopes, ScopeDebugInformation scope)2900 static bool AddScope (Collection<ScopeDebugInformation> scopes, ScopeDebugInformation scope) 2901 { 2902 if (scopes.IsNullOrEmpty ()) 2903 return false; 2904 2905 foreach (var sub_scope in scopes) { 2906 if (sub_scope.HasScopes && AddScope (sub_scope.Scopes, scope)) 2907 return true; 2908 2909 if (scope.Start.Offset >= sub_scope.Start.Offset && scope.End.Offset <= sub_scope.End.Offset) { 2910 sub_scope.Scopes.Add (scope); 2911 return true; 2912 } 2913 } 2914 2915 return false; 2916 } 2917 ReadLocalScope(Row<uint, Range, Range, uint, uint, uint> record)2918 ScopeDebugInformation ReadLocalScope (Row<uint, Range, Range, uint, uint, uint> record) 2919 { 2920 var scope = new ScopeDebugInformation 2921 { 2922 start = new InstructionOffset ((int) record.Col4), 2923 end = new InstructionOffset ((int) (record.Col4 + record.Col5)), 2924 token = new MetadataToken (TokenType.LocalScope, record.Col6), 2925 }; 2926 2927 if (record.Col1 > 0) 2928 scope.import = metadata.GetImportScope (record.Col1); 2929 2930 if (record.Col2.Length > 0) { 2931 scope.variables = new Collection<VariableDebugInformation> ((int) record.Col2.Length); 2932 for (uint i = 0; i < record.Col2.Length; i++) { 2933 var variable = ReadLocalVariable (record.Col2.Start + i); 2934 if (variable != null) 2935 scope.variables.Add (variable); 2936 } 2937 } 2938 2939 if (record.Col3.Length > 0) { 2940 scope.constants = new Collection<ConstantDebugInformation> ((int) record.Col3.Length); 2941 for (uint i = 0; i < record.Col3.Length; i++) { 2942 var constant = ReadLocalConstant (record.Col3.Start + i); 2943 if (constant != null) 2944 scope.constants.Add (constant); 2945 } 2946 } 2947 2948 return scope; 2949 } 2950 ReadLocalVariable(uint rid)2951 VariableDebugInformation ReadLocalVariable (uint rid) 2952 { 2953 if (!MoveTo (Table.LocalVariable, rid)) 2954 return null; 2955 2956 var attributes = (VariableAttributes) ReadUInt16 (); 2957 var index = ReadUInt16 (); 2958 var name = ReadString (); 2959 2960 var variable = new VariableDebugInformation (index, name) { Attributes = attributes, token = new MetadataToken (TokenType.LocalVariable, rid) }; 2961 variable.custom_infos = GetCustomDebugInformation (variable); 2962 return variable; 2963 } 2964 ReadLocalConstant(uint rid)2965 ConstantDebugInformation ReadLocalConstant (uint rid) 2966 { 2967 if (!MoveTo (Table.LocalConstant, rid)) 2968 return null; 2969 2970 var name = ReadString (); 2971 var signature = ReadSignature (ReadBlobIndex ()); 2972 var type = signature.ReadTypeSignature (); 2973 2974 object value; 2975 if (type.etype == ElementType.String) { 2976 if (signature.buffer [signature.position] != 0xff) { 2977 var bytes = signature.ReadBytes ((int) (signature.sig_length - (signature.position - signature.start))); 2978 value = Encoding.Unicode.GetString (bytes, 0, bytes.Length); 2979 } else 2980 value = null; 2981 } else if (type.IsTypeOf ("System", "Decimal")) { 2982 var b = signature.ReadByte (); 2983 value = new decimal (signature.ReadInt32 (), signature.ReadInt32 (), signature.ReadInt32 (), (b & 0x80) != 0, (byte) (b & 0x7f)); 2984 } else if (type.IsTypeOf ("System", "DateTime")) { 2985 value = new DateTime (signature.ReadInt64()); 2986 } else if (type.etype == ElementType.Object || type.etype == ElementType.None || type.etype == ElementType.Class) { 2987 value = null; 2988 } else 2989 value = signature.ReadConstantSignature (type.etype); 2990 2991 var constant = new ConstantDebugInformation (name, type, value) { token = new MetadataToken (TokenType.LocalConstant, rid) }; 2992 constant.custom_infos = GetCustomDebugInformation (constant); 2993 return constant; 2994 } 2995 InitializeImportScopes()2996 void InitializeImportScopes () 2997 { 2998 if (metadata.ImportScopes != null) 2999 return; 3000 3001 var length = MoveTo (Table.ImportScope); 3002 3003 metadata.ImportScopes = new ImportDebugInformation [length]; 3004 3005 for (int i = 1; i <= length; i++) { 3006 ReadTableIndex (Table.ImportScope); 3007 3008 var import = new ImportDebugInformation (); 3009 import.token = new MetadataToken (TokenType.ImportScope, i); 3010 3011 var signature = ReadSignature (ReadBlobIndex ()); 3012 while (signature.CanReadMore ()) 3013 import.Targets.Add (ReadImportTarget (signature)); 3014 3015 metadata.ImportScopes [i - 1] = import; 3016 } 3017 3018 MoveTo (Table.ImportScope); 3019 3020 for (int i = 0; i < length; i++) { 3021 var parent = ReadTableIndex (Table.ImportScope); 3022 3023 ReadBlobIndex (); 3024 3025 if (parent != 0) 3026 metadata.ImportScopes [i].Parent = metadata.GetImportScope (parent); 3027 } 3028 } 3029 ReadUTF8StringBlob(uint signature)3030 public string ReadUTF8StringBlob (uint signature) 3031 { 3032 return ReadStringBlob (signature, Encoding.UTF8); 3033 } 3034 ReadUnicodeStringBlob(uint signature)3035 string ReadUnicodeStringBlob (uint signature) 3036 { 3037 return ReadStringBlob (signature, Encoding.Unicode); 3038 } 3039 ReadStringBlob(uint signature, Encoding encoding)3040 string ReadStringBlob (uint signature, Encoding encoding) 3041 { 3042 byte [] blob; 3043 int index, count; 3044 3045 GetBlobView (signature, out blob, out index, out count); 3046 if (count == 0) 3047 return string.Empty; 3048 3049 return encoding.GetString (blob, index, count); 3050 } 3051 ReadImportTarget(SignatureReader signature)3052 ImportTarget ReadImportTarget (SignatureReader signature) 3053 { 3054 AssemblyNameReference reference = null; 3055 string @namespace = null; 3056 string alias = null; 3057 TypeReference type = null; 3058 3059 var kind = (ImportTargetKind) signature.ReadCompressedUInt32 (); 3060 switch (kind) { 3061 case ImportTargetKind.ImportNamespace: 3062 @namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); 3063 break; 3064 case ImportTargetKind.ImportNamespaceInAssembly: 3065 reference = metadata.GetAssemblyNameReference (signature.ReadCompressedUInt32 ()); 3066 @namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); 3067 break; 3068 case ImportTargetKind.ImportType: 3069 type = signature.ReadTypeToken (); 3070 break; 3071 case ImportTargetKind.ImportXmlNamespaceWithAlias: 3072 alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); 3073 @namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); 3074 break; 3075 case ImportTargetKind.ImportAlias: 3076 alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); 3077 break; 3078 case ImportTargetKind.DefineAssemblyAlias: 3079 alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); 3080 reference = metadata.GetAssemblyNameReference (signature.ReadCompressedUInt32 ()); 3081 break; 3082 case ImportTargetKind.DefineNamespaceAlias: 3083 alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); 3084 @namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); 3085 break; 3086 case ImportTargetKind.DefineNamespaceInAssemblyAlias: 3087 alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); 3088 reference = metadata.GetAssemblyNameReference (signature.ReadCompressedUInt32 ()); 3089 @namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); 3090 break; 3091 case ImportTargetKind.DefineTypeAlias: 3092 alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); 3093 type = signature.ReadTypeToken (); 3094 break; 3095 } 3096 3097 return new ImportTarget (kind) { 3098 alias = alias, 3099 type = type, 3100 @namespace = @namespace, 3101 reference = reference, 3102 }; 3103 } 3104 InitializeStateMachineMethods()3105 void InitializeStateMachineMethods () 3106 { 3107 if (metadata.StateMachineMethods != null) 3108 return; 3109 3110 var length = MoveTo (Table.StateMachineMethod); 3111 3112 metadata.StateMachineMethods = new Dictionary<uint, uint> (length); 3113 3114 for (int i = 0; i < length; i++) 3115 metadata.StateMachineMethods.Add (ReadTableIndex (Table.Method), ReadTableIndex (Table.Method)); 3116 } 3117 ReadStateMachineKickoffMethod(MethodDefinition method)3118 public MethodDefinition ReadStateMachineKickoffMethod (MethodDefinition method) 3119 { 3120 InitializeStateMachineMethods (); 3121 3122 uint rid; 3123 if (!metadata.TryGetStateMachineKickOffMethod (method, out rid)) 3124 return null; 3125 3126 return GetMethodDefinition (rid); 3127 } 3128 InitializeCustomDebugInformations()3129 void InitializeCustomDebugInformations () 3130 { 3131 if (metadata.CustomDebugInformations != null) 3132 return; 3133 3134 var length = MoveTo (Table.CustomDebugInformation); 3135 3136 metadata.CustomDebugInformations = new Dictionary<MetadataToken, Row<Guid, uint, uint> []> (); 3137 3138 for (uint i = 1; i <= length; i++) { 3139 var token = ReadMetadataToken (CodedIndex.HasCustomDebugInformation); 3140 var info = new Row<Guid, uint, uint> (ReadGuid (), ReadBlobIndex (), i); 3141 3142 Row<Guid, uint, uint> [] infos; 3143 metadata.CustomDebugInformations.TryGetValue (token, out infos); 3144 metadata.CustomDebugInformations [token] = infos.Add (info); 3145 } 3146 } 3147 GetCustomDebugInformation(ICustomDebugInformationProvider provider)3148 public Collection<CustomDebugInformation> GetCustomDebugInformation (ICustomDebugInformationProvider provider) 3149 { 3150 InitializeCustomDebugInformations (); 3151 3152 Row<Guid, uint, uint> [] rows; 3153 if (!metadata.CustomDebugInformations.TryGetValue (provider.MetadataToken, out rows)) 3154 return null; 3155 3156 var infos = new Collection<CustomDebugInformation> (rows.Length); 3157 3158 for (int i = 0; i < rows.Length; i++) { 3159 if (rows [i].Col1 == StateMachineScopeDebugInformation.KindIdentifier) { 3160 var signature = ReadSignature (rows [i].Col2); 3161 var scopes = new Collection<StateMachineScope> (); 3162 3163 while (signature.CanReadMore ()) { 3164 var start = signature.ReadInt32 (); 3165 var end = start + signature.ReadInt32 (); 3166 scopes.Add (new StateMachineScope (start, end)); 3167 } 3168 3169 var state_machine = new StateMachineScopeDebugInformation (); 3170 state_machine.scopes = scopes; 3171 3172 infos.Add (state_machine); 3173 } else if (rows [i].Col1 == AsyncMethodBodyDebugInformation.KindIdentifier) { 3174 var signature = ReadSignature (rows [i].Col2); 3175 3176 var catch_offset = signature.ReadInt32 () - 1; 3177 var yields = new Collection<InstructionOffset> (); 3178 var resumes = new Collection<InstructionOffset> (); 3179 var resume_methods = new Collection<MethodDefinition> (); 3180 3181 while (signature.CanReadMore ()) { 3182 yields.Add (new InstructionOffset (signature.ReadInt32 ())); 3183 resumes.Add (new InstructionOffset (signature.ReadInt32 ())); 3184 resume_methods.Add (GetMethodDefinition (signature.ReadCompressedUInt32 ())); 3185 } 3186 3187 var async_body = new AsyncMethodBodyDebugInformation (catch_offset); 3188 async_body.yields = yields; 3189 async_body.resumes = resumes; 3190 async_body.resume_methods = resume_methods; 3191 3192 infos.Add (async_body); 3193 } else if (rows [i].Col1 == EmbeddedSourceDebugInformation.KindIdentifier) { 3194 var signature = ReadSignature (rows [i].Col2); 3195 var format = signature.ReadInt32 (); 3196 var length = signature.sig_length - 4; 3197 3198 var info = null as CustomDebugInformation; 3199 3200 if (format == 0) { 3201 info = new EmbeddedSourceDebugInformation (signature.ReadBytes ((int) length), compress: false); 3202 } else if (format > 0) { 3203 var compressed_stream = new MemoryStream (signature.ReadBytes ((int) length)); 3204 var decompressed_document = new byte [format]; // if positive, format is the decompressed length of the document 3205 var decompressed_stream = new MemoryStream (decompressed_document); 3206 3207 using (var deflate_stream = new DeflateStream (compressed_stream, CompressionMode.Decompress, leaveOpen: true)) 3208 deflate_stream.CopyTo (decompressed_stream); 3209 3210 info = new EmbeddedSourceDebugInformation (decompressed_document, compress: true); 3211 } else if (format < 0) { 3212 info = new BinaryCustomDebugInformation (rows [i].Col1, ReadBlob (rows [i].Col2)); 3213 } 3214 3215 infos.Add (info); 3216 } else if (rows [i].Col1 == SourceLinkDebugInformation.KindIdentifier) { 3217 infos.Add (new SourceLinkDebugInformation (Encoding.UTF8.GetString (ReadBlob (rows [i].Col2)))); 3218 } else { 3219 infos.Add (new BinaryCustomDebugInformation (rows [i].Col1, ReadBlob (rows [i].Col2))); 3220 } 3221 3222 infos [i].token = new MetadataToken (TokenType.CustomDebugInformation, rows [i].Col3); 3223 } 3224 3225 return infos; 3226 } 3227 } 3228 3229 sealed class SignatureReader : ByteBuffer { 3230 3231 readonly MetadataReader reader; 3232 readonly internal uint start, sig_length; 3233 3234 TypeSystem TypeSystem { 3235 get { return reader.module.TypeSystem; } 3236 } 3237 SignatureReader(uint blob, MetadataReader reader)3238 public SignatureReader (uint blob, MetadataReader reader) 3239 : base (reader.image.BlobHeap.data) 3240 { 3241 this.reader = reader; 3242 this.position = (int) blob; 3243 this.sig_length = ReadCompressedUInt32(); 3244 this.start = (uint) this.position; 3245 } 3246 ReadTypeTokenSignature()3247 MetadataToken ReadTypeTokenSignature () 3248 { 3249 return CodedIndex.TypeDefOrRef.GetMetadataToken (ReadCompressedUInt32 ()); 3250 } 3251 GetGenericParameter(GenericParameterType type, uint var)3252 GenericParameter GetGenericParameter (GenericParameterType type, uint var) 3253 { 3254 var context = reader.context; 3255 int index = (int) var; 3256 3257 if (context == null) 3258 return GetUnboundGenericParameter (type, index); 3259 3260 IGenericParameterProvider provider; 3261 3262 switch (type) { 3263 case GenericParameterType.Type: 3264 provider = context.Type; 3265 break; 3266 case GenericParameterType.Method: 3267 provider = context.Method; 3268 break; 3269 default: 3270 throw new NotSupportedException (); 3271 } 3272 3273 if (!context.IsDefinition) 3274 CheckGenericContext (provider, index); 3275 3276 if (index >= provider.GenericParameters.Count) 3277 return GetUnboundGenericParameter (type, index); 3278 3279 return provider.GenericParameters [index]; 3280 } 3281 GetUnboundGenericParameter(GenericParameterType type, int index)3282 GenericParameter GetUnboundGenericParameter (GenericParameterType type, int index) 3283 { 3284 return new GenericParameter (index, type, reader.module); 3285 } 3286 CheckGenericContext(IGenericParameterProvider owner, int index)3287 static void CheckGenericContext (IGenericParameterProvider owner, int index) 3288 { 3289 var owner_parameters = owner.GenericParameters; 3290 3291 for (int i = owner_parameters.Count; i <= index; i++) 3292 owner_parameters.Add (new GenericParameter (owner)); 3293 } 3294 ReadGenericInstanceSignature(IGenericParameterProvider provider, IGenericInstance instance)3295 public void ReadGenericInstanceSignature (IGenericParameterProvider provider, IGenericInstance instance) 3296 { 3297 var arity = ReadCompressedUInt32 (); 3298 3299 if (!provider.IsDefinition) 3300 CheckGenericContext (provider, (int) arity - 1); 3301 3302 var instance_arguments = instance.GenericArguments; 3303 3304 for (int i = 0; i < arity; i++) 3305 instance_arguments.Add (ReadTypeSignature ()); 3306 } 3307 ReadArrayTypeSignature()3308 ArrayType ReadArrayTypeSignature () 3309 { 3310 var array = new ArrayType (ReadTypeSignature ()); 3311 3312 var rank = ReadCompressedUInt32 (); 3313 3314 var sizes = new uint [ReadCompressedUInt32 ()]; 3315 for (int i = 0; i < sizes.Length; i++) 3316 sizes [i] = ReadCompressedUInt32 (); 3317 3318 var low_bounds = new int [ReadCompressedUInt32 ()]; 3319 for (int i = 0; i < low_bounds.Length; i++) 3320 low_bounds [i] = ReadCompressedInt32 (); 3321 3322 array.Dimensions.Clear (); 3323 3324 for (int i = 0; i < rank; i++) { 3325 int? lower = null, upper = null; 3326 3327 if (i < low_bounds.Length) 3328 lower = low_bounds [i]; 3329 3330 if (i < sizes.Length) 3331 upper = lower + (int) sizes [i] - 1; 3332 3333 array.Dimensions.Add (new ArrayDimension (lower, upper)); 3334 } 3335 3336 return array; 3337 } 3338 GetTypeDefOrRef(MetadataToken token)3339 TypeReference GetTypeDefOrRef (MetadataToken token) 3340 { 3341 return reader.GetTypeDefOrRef (token); 3342 } 3343 ReadTypeSignature()3344 public TypeReference ReadTypeSignature () 3345 { 3346 return ReadTypeSignature ((ElementType) ReadByte ()); 3347 } 3348 ReadTypeToken()3349 public TypeReference ReadTypeToken () 3350 { 3351 return GetTypeDefOrRef (ReadTypeTokenSignature ()); 3352 } 3353 ReadTypeSignature(ElementType etype)3354 TypeReference ReadTypeSignature (ElementType etype) 3355 { 3356 switch (etype) { 3357 case ElementType.ValueType: { 3358 var value_type = GetTypeDefOrRef (ReadTypeTokenSignature ()); 3359 value_type.KnownValueType (); 3360 return value_type; 3361 } 3362 case ElementType.Class: 3363 return GetTypeDefOrRef (ReadTypeTokenSignature ()); 3364 case ElementType.Ptr: 3365 return new PointerType (ReadTypeSignature ()); 3366 case ElementType.FnPtr: { 3367 var fptr = new FunctionPointerType (); 3368 ReadMethodSignature (fptr); 3369 return fptr; 3370 } 3371 case ElementType.ByRef: 3372 return new ByReferenceType (ReadTypeSignature ()); 3373 case ElementType.Pinned: 3374 return new PinnedType (ReadTypeSignature ()); 3375 case ElementType.SzArray: 3376 return new ArrayType (ReadTypeSignature ()); 3377 case ElementType.Array: 3378 return ReadArrayTypeSignature (); 3379 case ElementType.CModOpt: 3380 return new OptionalModifierType ( 3381 GetTypeDefOrRef (ReadTypeTokenSignature ()), ReadTypeSignature ()); 3382 case ElementType.CModReqD: 3383 return new RequiredModifierType ( 3384 GetTypeDefOrRef (ReadTypeTokenSignature ()), ReadTypeSignature ()); 3385 case ElementType.Sentinel: 3386 return new SentinelType (ReadTypeSignature ()); 3387 case ElementType.Var: 3388 return GetGenericParameter (GenericParameterType.Type, ReadCompressedUInt32 ()); 3389 case ElementType.MVar: 3390 return GetGenericParameter (GenericParameterType.Method, ReadCompressedUInt32 ()); 3391 case ElementType.GenericInst: { 3392 var is_value_type = ReadByte () == (byte) ElementType.ValueType; 3393 var element_type = GetTypeDefOrRef (ReadTypeTokenSignature ()); 3394 var generic_instance = new GenericInstanceType (element_type); 3395 3396 ReadGenericInstanceSignature (element_type, generic_instance); 3397 3398 if (is_value_type) { 3399 generic_instance.KnownValueType (); 3400 element_type.GetElementType ().KnownValueType (); 3401 } 3402 3403 return generic_instance; 3404 } 3405 case ElementType.Object: return TypeSystem.Object; 3406 case ElementType.Void: return TypeSystem.Void; 3407 case ElementType.TypedByRef: return TypeSystem.TypedReference; 3408 case ElementType.I: return TypeSystem.IntPtr; 3409 case ElementType.U: return TypeSystem.UIntPtr; 3410 default: return GetPrimitiveType (etype); 3411 } 3412 } 3413 ReadMethodSignature(IMethodSignature method)3414 public void ReadMethodSignature (IMethodSignature method) 3415 { 3416 var calling_convention = ReadByte (); 3417 3418 const byte has_this = 0x20; 3419 const byte explicit_this = 0x40; 3420 3421 if ((calling_convention & has_this) != 0) { 3422 method.HasThis = true; 3423 calling_convention = (byte) (calling_convention & ~has_this); 3424 } 3425 3426 if ((calling_convention & explicit_this) != 0) { 3427 method.ExplicitThis = true; 3428 calling_convention = (byte) (calling_convention & ~explicit_this); 3429 } 3430 3431 method.CallingConvention = (MethodCallingConvention) calling_convention; 3432 3433 var generic_context = method as MethodReference; 3434 if (generic_context != null && !generic_context.DeclaringType.IsArray) 3435 reader.context = generic_context; 3436 3437 if ((calling_convention & 0x10) != 0) { 3438 var arity = ReadCompressedUInt32 (); 3439 3440 if (generic_context != null && !generic_context.IsDefinition) 3441 CheckGenericContext (generic_context, (int) arity -1 ); 3442 } 3443 3444 var param_count = ReadCompressedUInt32 (); 3445 3446 method.MethodReturnType.ReturnType = ReadTypeSignature (); 3447 3448 if (param_count == 0) 3449 return; 3450 3451 Collection<ParameterDefinition> parameters; 3452 3453 var method_ref = method as MethodReference; 3454 if (method_ref != null) 3455 parameters = method_ref.parameters = new ParameterDefinitionCollection (method, (int) param_count); 3456 else 3457 parameters = method.Parameters; 3458 3459 for (int i = 0; i < param_count; i++) 3460 parameters.Add (new ParameterDefinition (ReadTypeSignature ())); 3461 } 3462 ReadConstantSignature(ElementType type)3463 public object ReadConstantSignature (ElementType type) 3464 { 3465 return ReadPrimitiveValue (type); 3466 } 3467 ReadCustomAttributeConstructorArguments(CustomAttribute attribute, Collection<ParameterDefinition> parameters)3468 public void ReadCustomAttributeConstructorArguments (CustomAttribute attribute, Collection<ParameterDefinition> parameters) 3469 { 3470 var count = parameters.Count; 3471 if (count == 0) 3472 return; 3473 3474 attribute.arguments = new Collection<CustomAttributeArgument> (count); 3475 3476 for (int i = 0; i < count; i++) 3477 attribute.arguments.Add ( 3478 ReadCustomAttributeFixedArgument (parameters [i].ParameterType)); 3479 } 3480 ReadCustomAttributeFixedArgument(TypeReference type)3481 CustomAttributeArgument ReadCustomAttributeFixedArgument (TypeReference type) 3482 { 3483 if (type.IsArray) 3484 return ReadCustomAttributeFixedArrayArgument ((ArrayType) type); 3485 3486 return ReadCustomAttributeElement (type); 3487 } 3488 ReadCustomAttributeNamedArguments(ushort count, ref Collection<CustomAttributeNamedArgument> fields, ref Collection<CustomAttributeNamedArgument> properties)3489 public void ReadCustomAttributeNamedArguments (ushort count, ref Collection<CustomAttributeNamedArgument> fields, ref Collection<CustomAttributeNamedArgument> properties) 3490 { 3491 for (int i = 0; i < count; i++) { 3492 if (!CanReadMore ()) 3493 return; 3494 ReadCustomAttributeNamedArgument (ref fields, ref properties); 3495 } 3496 } 3497 ReadCustomAttributeNamedArgument(ref Collection<CustomAttributeNamedArgument> fields, ref Collection<CustomAttributeNamedArgument> properties)3498 void ReadCustomAttributeNamedArgument (ref Collection<CustomAttributeNamedArgument> fields, ref Collection<CustomAttributeNamedArgument> properties) 3499 { 3500 var kind = ReadByte (); 3501 var type = ReadCustomAttributeFieldOrPropType (); 3502 var name = ReadUTF8String (); 3503 3504 Collection<CustomAttributeNamedArgument> container; 3505 switch (kind) { 3506 case 0x53: 3507 container = GetCustomAttributeNamedArgumentCollection (ref fields); 3508 break; 3509 case 0x54: 3510 container = GetCustomAttributeNamedArgumentCollection (ref properties); 3511 break; 3512 default: 3513 throw new NotSupportedException (); 3514 } 3515 3516 container.Add (new CustomAttributeNamedArgument (name, ReadCustomAttributeFixedArgument (type))); 3517 } 3518 GetCustomAttributeNamedArgumentCollection(ref Collection<CustomAttributeNamedArgument> collection)3519 static Collection<CustomAttributeNamedArgument> GetCustomAttributeNamedArgumentCollection (ref Collection<CustomAttributeNamedArgument> collection) 3520 { 3521 if (collection != null) 3522 return collection; 3523 3524 return collection = new Collection<CustomAttributeNamedArgument> (); 3525 } 3526 ReadCustomAttributeFixedArrayArgument(ArrayType type)3527 CustomAttributeArgument ReadCustomAttributeFixedArrayArgument (ArrayType type) 3528 { 3529 var length = ReadUInt32 (); 3530 3531 if (length == 0xffffffff) 3532 return new CustomAttributeArgument (type, null); 3533 3534 if (length == 0) 3535 return new CustomAttributeArgument (type, Empty<CustomAttributeArgument>.Array); 3536 3537 var arguments = new CustomAttributeArgument [length]; 3538 var element_type = type.ElementType; 3539 3540 for (int i = 0; i < length; i++) 3541 arguments [i] = ReadCustomAttributeElement (element_type); 3542 3543 return new CustomAttributeArgument (type, arguments); 3544 } 3545 ReadCustomAttributeElement(TypeReference type)3546 CustomAttributeArgument ReadCustomAttributeElement (TypeReference type) 3547 { 3548 if (type.IsArray) 3549 return ReadCustomAttributeFixedArrayArgument ((ArrayType) type); 3550 3551 return new CustomAttributeArgument ( 3552 type, 3553 type.etype == ElementType.Object 3554 ? ReadCustomAttributeElement (ReadCustomAttributeFieldOrPropType ()) 3555 : ReadCustomAttributeElementValue (type)); 3556 } 3557 ReadCustomAttributeElementValue(TypeReference type)3558 object ReadCustomAttributeElementValue (TypeReference type) 3559 { 3560 var etype = type.etype; 3561 3562 switch (etype) { 3563 case ElementType.String: 3564 return ReadUTF8String (); 3565 case ElementType.None: 3566 if (type.IsTypeOf ("System", "Type")) 3567 return ReadTypeReference (); 3568 3569 return ReadCustomAttributeEnum (type); 3570 default: 3571 return ReadPrimitiveValue (etype); 3572 } 3573 } 3574 ReadPrimitiveValue(ElementType type)3575 object ReadPrimitiveValue (ElementType type) 3576 { 3577 switch (type) { 3578 case ElementType.Boolean: 3579 return ReadByte () == 1; 3580 case ElementType.I1: 3581 return (sbyte) ReadByte (); 3582 case ElementType.U1: 3583 return ReadByte (); 3584 case ElementType.Char: 3585 return (char) ReadUInt16 (); 3586 case ElementType.I2: 3587 return ReadInt16 (); 3588 case ElementType.U2: 3589 return ReadUInt16 (); 3590 case ElementType.I4: 3591 return ReadInt32 (); 3592 case ElementType.U4: 3593 return ReadUInt32 (); 3594 case ElementType.I8: 3595 return ReadInt64 (); 3596 case ElementType.U8: 3597 return ReadUInt64 (); 3598 case ElementType.R4: 3599 return ReadSingle (); 3600 case ElementType.R8: 3601 return ReadDouble (); 3602 default: 3603 throw new NotImplementedException (type.ToString ()); 3604 } 3605 } 3606 GetPrimitiveType(ElementType etype)3607 TypeReference GetPrimitiveType (ElementType etype) 3608 { 3609 switch (etype) { 3610 case ElementType.Boolean: 3611 return TypeSystem.Boolean; 3612 case ElementType.Char: 3613 return TypeSystem.Char; 3614 case ElementType.I1: 3615 return TypeSystem.SByte; 3616 case ElementType.U1: 3617 return TypeSystem.Byte; 3618 case ElementType.I2: 3619 return TypeSystem.Int16; 3620 case ElementType.U2: 3621 return TypeSystem.UInt16; 3622 case ElementType.I4: 3623 return TypeSystem.Int32; 3624 case ElementType.U4: 3625 return TypeSystem.UInt32; 3626 case ElementType.I8: 3627 return TypeSystem.Int64; 3628 case ElementType.U8: 3629 return TypeSystem.UInt64; 3630 case ElementType.R4: 3631 return TypeSystem.Single; 3632 case ElementType.R8: 3633 return TypeSystem.Double; 3634 case ElementType.String: 3635 return TypeSystem.String; 3636 default: 3637 throw new NotImplementedException (etype.ToString ()); 3638 } 3639 } 3640 ReadCustomAttributeFieldOrPropType()3641 TypeReference ReadCustomAttributeFieldOrPropType () 3642 { 3643 var etype = (ElementType) ReadByte (); 3644 3645 switch (etype) { 3646 case ElementType.Boxed: 3647 return TypeSystem.Object; 3648 case ElementType.SzArray: 3649 return new ArrayType (ReadCustomAttributeFieldOrPropType ()); 3650 case ElementType.Enum: 3651 return ReadTypeReference (); 3652 case ElementType.Type: 3653 return TypeSystem.LookupType ("System", "Type"); 3654 default: 3655 return GetPrimitiveType (etype); 3656 } 3657 } 3658 ReadTypeReference()3659 public TypeReference ReadTypeReference () 3660 { 3661 return TypeParser.ParseType (reader.module, ReadUTF8String ()); 3662 } 3663 ReadCustomAttributeEnum(TypeReference enum_type)3664 object ReadCustomAttributeEnum (TypeReference enum_type) 3665 { 3666 var type = enum_type.CheckedResolve (); 3667 if (!type.IsEnum) 3668 throw new ArgumentException (); 3669 3670 return ReadCustomAttributeElementValue (type.GetEnumUnderlyingType ()); 3671 } 3672 ReadSecurityAttribute()3673 public SecurityAttribute ReadSecurityAttribute () 3674 { 3675 var attribute = new SecurityAttribute (ReadTypeReference ()); 3676 3677 ReadCompressedUInt32 (); 3678 3679 ReadCustomAttributeNamedArguments ( 3680 (ushort) ReadCompressedUInt32 (), 3681 ref attribute.fields, 3682 ref attribute.properties); 3683 3684 return attribute; 3685 } 3686 ReadMarshalInfo()3687 public MarshalInfo ReadMarshalInfo () 3688 { 3689 var native = ReadNativeType (); 3690 switch (native) { 3691 case NativeType.Array: { 3692 var array = new ArrayMarshalInfo (); 3693 if (CanReadMore ()) 3694 array.element_type = ReadNativeType (); 3695 if (CanReadMore ()) 3696 array.size_parameter_index = (int) ReadCompressedUInt32 (); 3697 if (CanReadMore ()) 3698 array.size = (int) ReadCompressedUInt32 (); 3699 if (CanReadMore ()) 3700 array.size_parameter_multiplier = (int) ReadCompressedUInt32 (); 3701 return array; 3702 } 3703 case NativeType.SafeArray: { 3704 var array = new SafeArrayMarshalInfo (); 3705 if (CanReadMore ()) 3706 array.element_type = ReadVariantType (); 3707 return array; 3708 } 3709 case NativeType.FixedArray: { 3710 var array = new FixedArrayMarshalInfo (); 3711 if (CanReadMore ()) 3712 array.size = (int) ReadCompressedUInt32 (); 3713 if (CanReadMore ()) 3714 array.element_type = ReadNativeType (); 3715 return array; 3716 } 3717 case NativeType.FixedSysString: { 3718 var sys_string = new FixedSysStringMarshalInfo (); 3719 if (CanReadMore ()) 3720 sys_string.size = (int) ReadCompressedUInt32 (); 3721 return sys_string; 3722 } 3723 case NativeType.CustomMarshaler: { 3724 var marshaler = new CustomMarshalInfo (); 3725 var guid_value = ReadUTF8String (); 3726 marshaler.guid = !string.IsNullOrEmpty (guid_value) ? new Guid (guid_value) : Guid.Empty; 3727 marshaler.unmanaged_type = ReadUTF8String (); 3728 marshaler.managed_type = ReadTypeReference (); 3729 marshaler.cookie = ReadUTF8String (); 3730 return marshaler; 3731 } 3732 default: 3733 return new MarshalInfo (native); 3734 } 3735 } 3736 ReadNativeType()3737 NativeType ReadNativeType () 3738 { 3739 return (NativeType) ReadByte (); 3740 } 3741 ReadVariantType()3742 VariantType ReadVariantType () 3743 { 3744 return (VariantType) ReadByte (); 3745 } 3746 ReadUTF8String()3747 string ReadUTF8String () 3748 { 3749 if (buffer [position] == 0xff) { 3750 position++; 3751 return null; 3752 } 3753 3754 var length = (int) ReadCompressedUInt32 (); 3755 if (length == 0) 3756 return string.Empty; 3757 3758 var @string = Encoding.UTF8.GetString (buffer, position, 3759 buffer [position + length - 1] == 0 ? length - 1 : length); 3760 3761 position += length; 3762 return @string; 3763 } 3764 ReadDocumentName()3765 public string ReadDocumentName () 3766 { 3767 var separator = (char) buffer [position]; 3768 position++; 3769 3770 var builder = new StringBuilder (); 3771 for (int i = 0; CanReadMore (); i++) { 3772 if (i > 0 && separator != 0) 3773 builder.Append (separator); 3774 3775 uint part = ReadCompressedUInt32 (); 3776 if (part != 0) 3777 builder.Append (reader.ReadUTF8StringBlob (part)); 3778 } 3779 3780 return builder.ToString (); 3781 } 3782 ReadSequencePoints(Document document)3783 public Collection<SequencePoint> ReadSequencePoints (Document document) 3784 { 3785 var sequence_points = new Collection<SequencePoint> (); 3786 3787 ReadCompressedUInt32 (); // local_sig_token 3788 3789 if (document == null) 3790 document = reader.GetDocument (ReadCompressedUInt32 ()); 3791 3792 var offset = 0; 3793 var start_line = 0; 3794 var start_column = 0; 3795 var first_non_hidden = true; 3796 3797 for (var i = 0; CanReadMore (); i++) { 3798 var delta_il = (int) ReadCompressedUInt32 (); 3799 if (i > 0 && delta_il == 0) { 3800 document = reader.GetDocument (ReadCompressedUInt32 ()); 3801 continue; 3802 } 3803 3804 offset += delta_il; 3805 3806 var delta_lines = (int) ReadCompressedUInt32 (); 3807 var delta_columns = delta_lines == 0 3808 ? (int) ReadCompressedUInt32 () 3809 : ReadCompressedInt32 (); 3810 3811 if (delta_lines == 0 && delta_columns == 0) { 3812 sequence_points.Add (new SequencePoint (offset, document) { 3813 StartLine = 0xfeefee, 3814 EndLine = 0xfeefee, 3815 StartColumn = 0, 3816 EndColumn = 0, 3817 }); 3818 continue; 3819 } 3820 3821 if (first_non_hidden) { 3822 start_line = (int) ReadCompressedUInt32 (); 3823 start_column = (int) ReadCompressedUInt32 (); 3824 } else { 3825 start_line += ReadCompressedInt32 (); 3826 start_column += ReadCompressedInt32 (); 3827 } 3828 3829 sequence_points.Add (new SequencePoint (offset, document) { 3830 StartLine = start_line, 3831 StartColumn = start_column, 3832 EndLine = start_line + delta_lines, 3833 EndColumn = start_column + delta_columns, 3834 }); 3835 first_non_hidden = false; 3836 } 3837 3838 return sequence_points; 3839 } 3840 CanReadMore()3841 public bool CanReadMore () 3842 { 3843 return position - start < sig_length; 3844 } 3845 } 3846 } 3847