/Mono.Cecil/AssemblyWriter.cs
C# | 3334 lines | 2662 code | 659 blank | 13 comment | 387 complexity | c49fef0cb35b6db20b02f33df08c51b7 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
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 11using System; 12using System.Collections.Generic; 13using System.IO; 14using System.IO.Compression; 15using System.Text; 16using System.Security.Cryptography; 17 18using Mono; 19using Mono.Collections.Generic; 20using Mono.Cecil.Cil; 21using Mono.Cecil.Metadata; 22using Mono.Cecil.PE; 23 24using RVA = System.UInt32; 25using RID = System.UInt32; 26using CodedRID = System.UInt32; 27using StringIndex = System.UInt32; 28using BlobIndex = System.UInt32; 29using GuidIndex = System.UInt32; 30 31namespace Mono.Cecil { 32 33 using ModuleRow = Row<StringIndex, GuidIndex>; 34 using TypeRefRow = Row<CodedRID, StringIndex, StringIndex>; 35 using TypeDefRow = Row<TypeAttributes, StringIndex, StringIndex, CodedRID, RID, RID>; 36 using FieldRow = Row<FieldAttributes, StringIndex, BlobIndex>; 37 using MethodRow = Row<RVA, MethodImplAttributes, MethodAttributes, StringIndex, BlobIndex, RID>; 38 using ParamRow = Row<ParameterAttributes, ushort, StringIndex>; 39 using InterfaceImplRow = Row<uint, CodedRID>; 40 using MemberRefRow = Row<CodedRID, StringIndex, BlobIndex>; 41 using ConstantRow = Row<ElementType, CodedRID, BlobIndex>; 42 using CustomAttributeRow = Row<CodedRID, CodedRID, BlobIndex>; 43 using FieldMarshalRow = Row<CodedRID, BlobIndex>; 44 using DeclSecurityRow = Row<SecurityAction, CodedRID, BlobIndex>; 45 using ClassLayoutRow = Row<ushort, uint, RID>; 46 using FieldLayoutRow = Row<uint, RID>; 47 using EventMapRow = Row<RID, RID>; 48 using EventRow = Row<EventAttributes, StringIndex, CodedRID>; 49 using PropertyMapRow = Row<RID, RID>; 50 using PropertyRow = Row<PropertyAttributes, StringIndex, BlobIndex>; 51 using MethodSemanticsRow = Row<MethodSemanticsAttributes, RID, CodedRID>; 52 using MethodImplRow = Row<RID, CodedRID, CodedRID>; 53 using ImplMapRow = Row<PInvokeAttributes, CodedRID, StringIndex, RID>; 54 using FieldRVARow = Row<RVA, RID>; 55 using AssemblyRow = Row<AssemblyHashAlgorithm, ushort, ushort, ushort, ushort, AssemblyAttributes, uint, uint, uint>; 56 using AssemblyRefRow = Row<ushort, ushort, ushort, ushort, AssemblyAttributes, uint, uint, uint, uint>; 57 using FileRow = Row<FileAttributes, StringIndex, BlobIndex>; 58 using ExportedTypeRow = Row<TypeAttributes, uint, StringIndex, StringIndex, CodedRID>; 59 using ManifestResourceRow = Row<uint, ManifestResourceAttributes, StringIndex, CodedRID>; 60 using NestedClassRow = Row<RID, RID>; 61 using GenericParamRow = Row<ushort, GenericParameterAttributes, CodedRID, StringIndex>; 62 using MethodSpecRow = Row<CodedRID, BlobIndex>; 63 using GenericParamConstraintRow = Row<RID, CodedRID>; 64 using DocumentRow = Row<BlobIndex, GuidIndex, BlobIndex, GuidIndex>; 65 using MethodDebugInformationRow = Row<RID, BlobIndex>; 66 using LocalScopeRow = Row<RID, RID, RID, RID, uint, uint>; 67 using LocalVariableRow = Row<VariableAttributes, ushort, StringIndex>; 68 using LocalConstantRow = Row<StringIndex, BlobIndex>; 69 using ImportScopeRow = Row<RID, BlobIndex>; 70 using StateMachineMethodRow = Row<RID, RID>; 71 using CustomDebugInformationRow = Row<CodedRID, GuidIndex, BlobIndex>; 72 73 static class ModuleWriter { 74 75 public static void WriteModule (ModuleDefinition module, Disposable<Stream> stream, WriterParameters parameters) 76 { 77 using (stream) 78 Write (module, stream, parameters); 79 } 80 81 static void Write (ModuleDefinition module, Disposable<Stream> stream, WriterParameters parameters) 82 { 83 if ((module.Attributes & ModuleAttributes.ILOnly) == 0) 84 throw new NotSupportedException ("Writing mixed-mode assemblies is not supported"); 85 86 if (module.HasImage && module.ReadingMode == ReadingMode.Deferred) { 87 var immediate_reader = new ImmediateModuleReader (module.Image); 88 immediate_reader.ReadModule (module, resolve_attributes: false); 89 immediate_reader.ReadSymbols (module); 90 } 91 92 module.MetadataSystem.Clear (); 93 94 if (module.symbol_reader != null) 95 module.symbol_reader.Dispose (); 96 97 var name = module.assembly != null ? module.assembly.Name : null; 98 var fq_name = stream.value.GetFileName (); 99 var timestamp = parameters.Timestamp ?? module.timestamp; 100 var symbol_writer_provider = parameters.SymbolWriterProvider; 101 102 if (symbol_writer_provider == null && parameters.WriteSymbols) 103 symbol_writer_provider = new DefaultSymbolWriterProvider (); 104 105 if (parameters.HasStrongNameKey && name != null) { 106 name.PublicKey = CryptoService.GetPublicKey (parameters); 107 module.Attributes |= ModuleAttributes.StrongNameSigned; 108 } 109 110 if (parameters.DeterministicMvid) 111 module.Mvid = Guid.Empty; 112 113 var metadata = new MetadataBuilder (module, fq_name, timestamp, symbol_writer_provider); 114 try { 115 module.metadata_builder = metadata; 116 117 using (var symbol_writer = GetSymbolWriter (module, fq_name, symbol_writer_provider, parameters)) { 118 metadata.SetSymbolWriter (symbol_writer); 119 BuildMetadata (module, metadata); 120 121 if (parameters.DeterministicMvid) 122 metadata.ComputeDeterministicMvid (); 123 124 var writer = ImageWriter.CreateWriter (module, metadata, stream); 125 stream.value.SetLength (0); 126 writer.WriteImage (); 127 128 if (parameters.HasStrongNameKey) 129 CryptoService.StrongName (stream.value, writer, parameters); 130 } 131 } finally { 132 module.metadata_builder = null; 133 } 134 } 135 136 static void BuildMetadata (ModuleDefinition module, MetadataBuilder metadata) 137 { 138 if (!module.HasImage) { 139 metadata.BuildMetadata (); 140 return; 141 } 142 143 module.Read (metadata, (builder, _) => { 144 builder.BuildMetadata (); 145 return builder; 146 }); 147 } 148 149 static ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fq_name, ISymbolWriterProvider symbol_writer_provider, WriterParameters parameters) 150 { 151 if (symbol_writer_provider == null) 152 return null; 153 154 if (parameters.SymbolStream != null) 155 return symbol_writer_provider.GetSymbolWriter (module, parameters.SymbolStream); 156 157 return symbol_writer_provider.GetSymbolWriter (module, fq_name); 158 } 159 } 160 161 abstract class MetadataTable { 162 163 public abstract int Length { get; } 164 165 public bool IsLarge { 166 get { return Length > ushort.MaxValue; } 167 } 168 169 public abstract void Write (TableHeapBuffer buffer); 170 public abstract void Sort (); 171 } 172 173 abstract class OneRowTable<TRow> : MetadataTable where TRow : struct { 174 175 internal TRow row; 176 177 public sealed override int Length { 178 get { return 1; } 179 } 180 181 public sealed override void Sort () 182 { 183 } 184 } 185 186 abstract class MetadataTable<TRow> : MetadataTable where TRow : struct { 187 188 internal TRow [] rows = new TRow [2]; 189 internal int length; 190 191 public sealed override int Length { 192 get { return length; } 193 } 194 195 public int AddRow (TRow row) 196 { 197 if (rows.Length == length) 198 Grow (); 199 200 rows [length++] = row; 201 return length; 202 } 203 204 void Grow () 205 { 206 var rows = new TRow [this.rows.Length * 2]; 207 Array.Copy (this.rows, rows, this.rows.Length); 208 this.rows = rows; 209 } 210 211 public override void Sort () 212 { 213 } 214 } 215 216 abstract class SortedTable<TRow> : MetadataTable<TRow>, IComparer<TRow> where TRow : struct { 217 218 public sealed override void Sort () 219 { 220 MergeSort<TRow>.Sort (rows, 0, this.length, this); 221 } 222 223 protected static int Compare (uint x, uint y) 224 { 225 return x == y ? 0 : x > y ? 1 : -1; 226 } 227 228 public abstract int Compare (TRow x, TRow y); 229 } 230 231 sealed class ModuleTable : OneRowTable<ModuleRow> { 232 233 public override void Write (TableHeapBuffer buffer) 234 { 235 buffer.WriteUInt16 (0); // Generation 236 buffer.WriteString (row.Col1); // Name 237 buffer.WriteGuid (row.Col2); // Mvid 238 buffer.WriteUInt16 (0); // EncId 239 buffer.WriteUInt16 (0); // EncBaseId 240 } 241 } 242 243 sealed class TypeRefTable : MetadataTable<TypeRefRow> { 244 245 public override void Write (TableHeapBuffer buffer) 246 { 247 for (int i = 0; i < length; i++) { 248 buffer.WriteCodedRID ( 249 rows [i].Col1, CodedIndex.ResolutionScope); // Scope 250 buffer.WriteString (rows [i].Col2); // Name 251 buffer.WriteString (rows [i].Col3); // Namespace 252 } 253 } 254 } 255 256 sealed class TypeDefTable : MetadataTable<TypeDefRow> { 257 258 public override void Write (TableHeapBuffer buffer) 259 { 260 for (int i = 0; i < length; i++) { 261 buffer.WriteUInt32 ((uint) rows [i].Col1); // Attributes 262 buffer.WriteString (rows [i].Col2); // Name 263 buffer.WriteString (rows [i].Col3); // Namespace 264 buffer.WriteCodedRID ( 265 rows [i].Col4, CodedIndex.TypeDefOrRef); // Extends 266 buffer.WriteRID (rows [i].Col5, Table.Field); // FieldList 267 buffer.WriteRID (rows [i].Col6, Table.Method); // MethodList 268 } 269 } 270 } 271 272 sealed class FieldTable : MetadataTable<FieldRow> { 273 274 public override void Write (TableHeapBuffer buffer) 275 { 276 for (int i = 0; i < length; i++) { 277 buffer.WriteUInt16 ((ushort) rows [i].Col1); // Attributes 278 buffer.WriteString (rows [i].Col2); // Name 279 buffer.WriteBlob (rows [i].Col3); // Signature 280 } 281 } 282 } 283 284 sealed class MethodTable : MetadataTable<MethodRow> { 285 286 public override void Write (TableHeapBuffer buffer) 287 { 288 for (int i = 0; i < length; i++) { 289 buffer.WriteUInt32 (rows [i].Col1); // RVA 290 buffer.WriteUInt16 ((ushort) rows [i].Col2); // ImplFlags 291 buffer.WriteUInt16 ((ushort) rows [i].Col3); // Flags 292 buffer.WriteString (rows [i].Col4); // Name 293 buffer.WriteBlob (rows [i].Col5); // Signature 294 buffer.WriteRID (rows [i].Col6, Table.Param); // ParamList 295 } 296 } 297 } 298 299 sealed class ParamTable : MetadataTable<ParamRow> { 300 301 public override void Write (TableHeapBuffer buffer) 302 { 303 for (int i = 0; i < length; i++) { 304 buffer.WriteUInt16 ((ushort) rows [i].Col1); // Attributes 305 buffer.WriteUInt16 (rows [i].Col2); // Sequence 306 buffer.WriteString (rows [i].Col3); // Name 307 } 308 } 309 } 310 311 sealed class InterfaceImplTable : MetadataTable<InterfaceImplRow> { 312 313 public override void Write (TableHeapBuffer buffer) 314 { 315 for (int i = 0; i < length; i++) { 316 buffer.WriteRID (rows [i].Col1, Table.TypeDef); // Class 317 buffer.WriteCodedRID (rows [i].Col2, CodedIndex.TypeDefOrRef); // Interface 318 } 319 } 320 321 /*public override int Compare (InterfaceImplRow x, InterfaceImplRow y) 322 { 323 return (int) (x.Col1 == y.Col1 ? y.Col2 - x.Col2 : x.Col1 - y.Col1); 324 }*/ 325 } 326 327 sealed class MemberRefTable : MetadataTable<MemberRefRow> { 328 329 public override void Write (TableHeapBuffer buffer) 330 { 331 for (int i = 0; i < length; i++) { 332 buffer.WriteCodedRID (rows [i].Col1, CodedIndex.MemberRefParent); 333 buffer.WriteString (rows [i].Col2); 334 buffer.WriteBlob (rows [i].Col3); 335 } 336 } 337 } 338 339 sealed class ConstantTable : SortedTable<ConstantRow> { 340 341 public override void Write (TableHeapBuffer buffer) 342 { 343 for (int i = 0; i < length; i++) { 344 buffer.WriteUInt16 ((ushort) rows [i].Col1); 345 buffer.WriteCodedRID (rows [i].Col2, CodedIndex.HasConstant); 346 buffer.WriteBlob (rows [i].Col3); 347 } 348 } 349 350 public override int Compare (ConstantRow x, ConstantRow y) 351 { 352 return Compare (x.Col2, y.Col2); 353 } 354 } 355 356 sealed class CustomAttributeTable : SortedTable<CustomAttributeRow> { 357 358 public override void Write (TableHeapBuffer buffer) 359 { 360 for (int i = 0; i < length; i++) { 361 buffer.WriteCodedRID (rows [i].Col1, CodedIndex.HasCustomAttribute); // Parent 362 buffer.WriteCodedRID (rows [i].Col2, CodedIndex.CustomAttributeType); // Type 363 buffer.WriteBlob (rows [i].Col3); 364 } 365 } 366 367 public override int Compare (CustomAttributeRow x, CustomAttributeRow y) 368 { 369 return Compare (x.Col1, y.Col1); 370 } 371 } 372 373 sealed class FieldMarshalTable : SortedTable<FieldMarshalRow> { 374 375 public override void Write (TableHeapBuffer buffer) 376 { 377 for (int i = 0; i < length; i++) { 378 buffer.WriteCodedRID (rows [i].Col1, CodedIndex.HasFieldMarshal); 379 buffer.WriteBlob (rows [i].Col2); 380 } 381 } 382 383 public override int Compare (FieldMarshalRow x, FieldMarshalRow y) 384 { 385 return Compare (x.Col1, y.Col1); 386 } 387 } 388 389 sealed class DeclSecurityTable : SortedTable<DeclSecurityRow> { 390 391 public override void Write (TableHeapBuffer buffer) 392 { 393 for (int i = 0; i < length; i++) { 394 buffer.WriteUInt16 ((ushort) rows [i].Col1); 395 buffer.WriteCodedRID (rows [i].Col2, CodedIndex.HasDeclSecurity); 396 buffer.WriteBlob (rows [i].Col3); 397 } 398 } 399 400 public override int Compare (DeclSecurityRow x, DeclSecurityRow y) 401 { 402 return Compare (x.Col2, y.Col2); 403 } 404 } 405 406 sealed class ClassLayoutTable : SortedTable<ClassLayoutRow> { 407 408 public override void Write (TableHeapBuffer buffer) 409 { 410 for (int i = 0; i < length; i++) { 411 buffer.WriteUInt16 (rows [i].Col1); // PackingSize 412 buffer.WriteUInt32 (rows [i].Col2); // ClassSize 413 buffer.WriteRID (rows [i].Col3, Table.TypeDef); // Parent 414 } 415 } 416 417 public override int Compare (ClassLayoutRow x, ClassLayoutRow y) 418 { 419 return Compare (x.Col3, y.Col3); 420 } 421 } 422 423 sealed class FieldLayoutTable : SortedTable<FieldLayoutRow> { 424 425 public override void Write (TableHeapBuffer buffer) 426 { 427 for (int i = 0; i < length; i++) { 428 buffer.WriteUInt32 (rows [i].Col1); // Offset 429 buffer.WriteRID (rows [i].Col2, Table.Field); // Parent 430 } 431 } 432 433 public override int Compare (FieldLayoutRow x, FieldLayoutRow y) 434 { 435 return Compare (x.Col2, y.Col2); 436 } 437 } 438 439 sealed class StandAloneSigTable : MetadataTable<uint> { 440 441 public override void Write (TableHeapBuffer buffer) 442 { 443 for (int i = 0; i < length; i++) 444 buffer.WriteBlob (rows [i]); 445 } 446 } 447 448 sealed class EventMapTable : MetadataTable<EventMapRow> { 449 450 public override void Write (TableHeapBuffer buffer) 451 { 452 for (int i = 0; i < length; i++) { 453 buffer.WriteRID (rows [i].Col1, Table.TypeDef); // Parent 454 buffer.WriteRID (rows [i].Col2, Table.Event); // EventList 455 } 456 } 457 } 458 459 sealed class EventTable : MetadataTable<EventRow> { 460 461 public override void Write (TableHeapBuffer buffer) 462 { 463 for (int i = 0; i < length; i++) { 464 buffer.WriteUInt16 ((ushort) rows [i].Col1); // Flags 465 buffer.WriteString (rows [i].Col2); // Name 466 buffer.WriteCodedRID (rows [i].Col3, CodedIndex.TypeDefOrRef); // EventType 467 } 468 } 469 } 470 471 sealed class PropertyMapTable : MetadataTable<PropertyMapRow> { 472 473 public override void Write (TableHeapBuffer buffer) 474 { 475 for (int i = 0; i < length; i++) { 476 buffer.WriteRID (rows [i].Col1, Table.TypeDef); // Parent 477 buffer.WriteRID (rows [i].Col2, Table.Property); // PropertyList 478 } 479 } 480 } 481 482 sealed class PropertyTable : MetadataTable<PropertyRow> { 483 484 public override void Write (TableHeapBuffer buffer) 485 { 486 for (int i = 0; i < length; i++) { 487 buffer.WriteUInt16 ((ushort) rows [i].Col1); // Flags 488 buffer.WriteString (rows [i].Col2); // Name 489 buffer.WriteBlob (rows [i].Col3); // Type 490 } 491 } 492 } 493 494 sealed class MethodSemanticsTable : SortedTable<MethodSemanticsRow> { 495 496 public override void Write (TableHeapBuffer buffer) 497 { 498 for (int i = 0; i < length; i++) { 499 buffer.WriteUInt16 ((ushort) rows [i].Col1); // Flags 500 buffer.WriteRID (rows [i].Col2, Table.Method); // Method 501 buffer.WriteCodedRID (rows [i].Col3, CodedIndex.HasSemantics); // Association 502 } 503 } 504 505 public override int Compare (MethodSemanticsRow x, MethodSemanticsRow y) 506 { 507 return Compare (x.Col3, y.Col3); 508 } 509 } 510 511 sealed class MethodImplTable : MetadataTable<MethodImplRow> { 512 513 public override void Write (TableHeapBuffer buffer) 514 { 515 for (int i = 0; i < length; i++) { 516 buffer.WriteRID (rows [i].Col1, Table.TypeDef); // Class 517 buffer.WriteCodedRID (rows [i].Col2, CodedIndex.MethodDefOrRef); // MethodBody 518 buffer.WriteCodedRID (rows [i].Col3, CodedIndex.MethodDefOrRef); // MethodDeclaration 519 } 520 } 521 } 522 523 sealed class ModuleRefTable : MetadataTable<uint> { 524 525 public override void Write (TableHeapBuffer buffer) 526 { 527 for (int i = 0; i < length; i++) 528 buffer.WriteString (rows [i]); // Name 529 } 530 } 531 532 sealed class TypeSpecTable : MetadataTable<uint> { 533 534 public override void Write (TableHeapBuffer buffer) 535 { 536 for (int i = 0; i < length; i++) 537 buffer.WriteBlob (rows [i]); // Signature 538 } 539 } 540 541 sealed class ImplMapTable : SortedTable<ImplMapRow> { 542 543 public override void Write (TableHeapBuffer buffer) 544 { 545 for (int i = 0; i < length; i++) { 546 buffer.WriteUInt16 ((ushort) rows [i].Col1); // Flags 547 buffer.WriteCodedRID (rows [i].Col2, CodedIndex.MemberForwarded); // MemberForwarded 548 buffer.WriteString (rows [i].Col3); // ImportName 549 buffer.WriteRID (rows [i].Col4, Table.ModuleRef); // ImportScope 550 } 551 } 552 553 public override int Compare (ImplMapRow x, ImplMapRow y) 554 { 555 return Compare (x.Col2, y.Col2); 556 } 557 } 558 559 sealed class FieldRVATable : SortedTable<FieldRVARow> { 560 561 internal int position; 562 563 public override void Write (TableHeapBuffer buffer) 564 { 565 position = buffer.position; 566 for (int i = 0; i < length; i++) { 567 buffer.WriteUInt32 (rows [i].Col1); // RVA 568 buffer.WriteRID (rows [i].Col2, Table.Field); // Field 569 } 570 } 571 572 public override int Compare (FieldRVARow x, FieldRVARow y) 573 { 574 return Compare (x.Col2, y.Col2); 575 } 576 } 577 578 sealed class AssemblyTable : OneRowTable<AssemblyRow> { 579 580 public override void Write (TableHeapBuffer buffer) 581 { 582 buffer.WriteUInt32 ((uint) row.Col1); // AssemblyHashAlgorithm 583 buffer.WriteUInt16 (row.Col2); // MajorVersion 584 buffer.WriteUInt16 (row.Col3); // MinorVersion 585 buffer.WriteUInt16 (row.Col4); // Build 586 buffer.WriteUInt16 (row.Col5); // Revision 587 buffer.WriteUInt32 ((uint) row.Col6); // Flags 588 buffer.WriteBlob (row.Col7); // PublicKey 589 buffer.WriteString (row.Col8); // Name 590 buffer.WriteString (row.Col9); // Culture 591 } 592 } 593 594 sealed class AssemblyRefTable : MetadataTable<AssemblyRefRow> { 595 596 public override void Write (TableHeapBuffer buffer) 597 { 598 for (int i = 0; i < length; i++) { 599 buffer.WriteUInt16 (rows [i].Col1); // MajorVersion 600 buffer.WriteUInt16 (rows [i].Col2); // MinorVersion 601 buffer.WriteUInt16 (rows [i].Col3); // Build 602 buffer.WriteUInt16 (rows [i].Col4); // Revision 603 buffer.WriteUInt32 ((uint) rows [i].Col5); // Flags 604 buffer.WriteBlob (rows [i].Col6); // PublicKeyOrToken 605 buffer.WriteString (rows [i].Col7); // Name 606 buffer.WriteString (rows [i].Col8); // Culture 607 buffer.WriteBlob (rows [i].Col9); // Hash 608 } 609 } 610 } 611 612 sealed class FileTable : MetadataTable<FileRow> { 613 614 public override void Write (TableHeapBuffer buffer) 615 { 616 for (int i = 0; i < length; i++) { 617 buffer.WriteUInt32 ((uint) rows [i].Col1); 618 buffer.WriteString (rows [i].Col2); 619 buffer.WriteBlob (rows [i].Col3); 620 } 621 } 622 } 623 624 sealed class ExportedTypeTable : MetadataTable<ExportedTypeRow> { 625 626 public override void Write (TableHeapBuffer buffer) 627 { 628 for (int i = 0; i < length; i++) { 629 buffer.WriteUInt32 ((uint) rows [i].Col1); 630 buffer.WriteUInt32 (rows [i].Col2); 631 buffer.WriteString (rows [i].Col3); 632 buffer.WriteString (rows [i].Col4); 633 buffer.WriteCodedRID (rows [i].Col5, CodedIndex.Implementation); 634 } 635 } 636 } 637 638 sealed class ManifestResourceTable : MetadataTable<ManifestResourceRow> { 639 640 public override void Write (TableHeapBuffer buffer) 641 { 642 for (int i = 0; i < length; i++) { 643 buffer.WriteUInt32 (rows [i].Col1); 644 buffer.WriteUInt32 ((uint) rows [i].Col2); 645 buffer.WriteString (rows [i].Col3); 646 buffer.WriteCodedRID (rows [i].Col4, CodedIndex.Implementation); 647 } 648 } 649 } 650 651 sealed class NestedClassTable : SortedTable<NestedClassRow> { 652 653 public override void Write (TableHeapBuffer buffer) 654 { 655 for (int i = 0; i < length; i++) { 656 buffer.WriteRID (rows [i].Col1, Table.TypeDef); // NestedClass 657 buffer.WriteRID (rows [i].Col2, Table.TypeDef); // EnclosingClass 658 } 659 } 660 661 public override int Compare (NestedClassRow x, NestedClassRow y) 662 { 663 return Compare (x.Col1, y.Col1); 664 } 665 } 666 667 sealed class GenericParamTable : MetadataTable<GenericParamRow> { 668 669 public override void Write (TableHeapBuffer buffer) 670 { 671 for (int i = 0; i < length; i++) { 672 buffer.WriteUInt16 (rows [i].Col1); // Number 673 buffer.WriteUInt16 ((ushort) rows [i].Col2); // Flags 674 buffer.WriteCodedRID (rows [i].Col3, CodedIndex.TypeOrMethodDef); // Owner 675 buffer.WriteString (rows [i].Col4); // Name 676 } 677 } 678 } 679 680 sealed class MethodSpecTable : MetadataTable<MethodSpecRow> { 681 682 public override void Write (TableHeapBuffer buffer) 683 { 684 for (int i = 0; i < length; i++) { 685 buffer.WriteCodedRID (rows [i].Col1, CodedIndex.MethodDefOrRef); // Method 686 buffer.WriteBlob (rows [i].Col2); // Instantiation 687 } 688 } 689 } 690 691 sealed class GenericParamConstraintTable : MetadataTable<GenericParamConstraintRow> { 692 693 public override void Write (TableHeapBuffer buffer) 694 { 695 for (int i = 0; i < length; i++) { 696 buffer.WriteRID (rows [i].Col1, Table.GenericParam); // Owner 697 buffer.WriteCodedRID (rows [i].Col2, CodedIndex.TypeDefOrRef); // Constraint 698 } 699 } 700 } 701 702 sealed class DocumentTable : MetadataTable<DocumentRow> { 703 704 public override void Write (TableHeapBuffer buffer) 705 { 706 for (int i = 0; i < length; i++) { 707 buffer.WriteBlob (rows [i].Col1); // Name 708 buffer.WriteGuid (rows [i].Col2); // HashAlgorithm 709 buffer.WriteBlob (rows [i].Col3); // Hash 710 buffer.WriteGuid (rows [i].Col4); // Language 711 } 712 } 713 } 714 715 sealed class MethodDebugInformationTable : MetadataTable<MethodDebugInformationRow> { 716 717 public override void Write (TableHeapBuffer buffer) 718 { 719 for (int i = 0; i < length; i++) { 720 buffer.WriteRID (rows [i].Col1, Table.Document); // Document 721 buffer.WriteBlob (rows [i].Col2); // SequencePoints 722 } 723 } 724 } 725 726 sealed class LocalScopeTable : MetadataTable<LocalScopeRow> { 727 728 public override void Write (TableHeapBuffer buffer) 729 { 730 for (int i = 0; i < length; i++) { 731 buffer.WriteRID (rows [i].Col1, Table.Method); // Method 732 buffer.WriteRID (rows [i].Col2, Table.ImportScope); // ImportScope 733 buffer.WriteRID (rows [i].Col3, Table.LocalVariable); // VariableList 734 buffer.WriteRID (rows [i].Col4, Table.LocalConstant); // ConstantList 735 buffer.WriteUInt32 (rows [i].Col5); // StartOffset 736 buffer.WriteUInt32 (rows [i].Col6); // Length 737 } 738 } 739 } 740 741 sealed class LocalVariableTable : MetadataTable<LocalVariableRow> { 742 743 public override void Write (TableHeapBuffer buffer) 744 { 745 for (int i = 0; i < length; i++) { 746 buffer.WriteUInt16 ((ushort) rows [i].Col1); // Attributes 747 buffer.WriteUInt16 (rows [i].Col2); // Index 748 buffer.WriteString (rows [i].Col3); // Name 749 } 750 } 751 } 752 753 sealed class LocalConstantTable : MetadataTable<LocalConstantRow> { 754 755 public override void Write (TableHeapBuffer buffer) 756 { 757 for (int i = 0; i < length; i++) { 758 buffer.WriteString (rows [i].Col1); // Name 759 buffer.WriteBlob (rows [i].Col2); // Signature 760 } 761 } 762 } 763 764 sealed class ImportScopeTable : MetadataTable<ImportScopeRow> { 765 766 public override void Write (TableHeapBuffer buffer) 767 { 768 for (int i = 0; i < length; i++) { 769 buffer.WriteRID (rows [i].Col1, Table.ImportScope); // Parent 770 buffer.WriteBlob (rows [i].Col2); // Imports 771 } 772 } 773 } 774 775 sealed class StateMachineMethodTable : MetadataTable<StateMachineMethodRow> { 776 777 public override void Write (TableHeapBuffer buffer) 778 { 779 for (int i = 0; i < length; i++) { 780 buffer.WriteRID (rows [i].Col1, Table.Method); // MoveNextMethod 781 buffer.WriteRID (rows [i].Col2, Table.Method); // KickoffMethod 782 } 783 } 784 } 785 786 sealed class CustomDebugInformationTable : SortedTable<CustomDebugInformationRow> { 787 788 public override void Write (TableHeapBuffer buffer) 789 { 790 for (int i = 0; i < length; i++) { 791 buffer.WriteCodedRID (rows [i].Col1, CodedIndex.HasCustomDebugInformation); // Parent 792 buffer.WriteGuid (rows [i].Col2); // Kind 793 buffer.WriteBlob (rows [i].Col3); // Value 794 } 795 } 796 797 public override int Compare (CustomDebugInformationRow x, CustomDebugInformationRow y) 798 { 799 return Compare(x.Col1, y.Col1); 800 } 801 } 802 803 sealed class MetadataBuilder { 804 805 readonly internal ModuleDefinition module; 806 readonly internal ISymbolWriterProvider symbol_writer_provider; 807 internal ISymbolWriter symbol_writer; 808 readonly internal TextMap text_map; 809 readonly internal string fq_name; 810 readonly internal uint timestamp; 811 812 readonly Dictionary<TypeRefRow, MetadataToken> type_ref_map; 813 readonly Dictionary<uint, MetadataToken> type_spec_map; 814 readonly Dictionary<MemberRefRow, MetadataToken> member_ref_map; 815 readonly Dictionary<MethodSpecRow, MetadataToken> method_spec_map; 816 readonly Collection<GenericParameter> generic_parameters; 817 818 readonly internal CodeWriter code; 819 readonly internal DataBuffer data; 820 readonly internal ResourceBuffer resources; 821 readonly internal StringHeapBuffer string_heap; 822 readonly internal GuidHeapBuffer guid_heap; 823 readonly internal UserStringHeapBuffer user_string_heap; 824 readonly internal BlobHeapBuffer blob_heap; 825 readonly internal TableHeapBuffer table_heap; 826 readonly internal PdbHeapBuffer pdb_heap; 827 828 internal MetadataToken entry_point; 829 830 internal RID type_rid = 1; 831 internal RID field_rid = 1; 832 internal RID method_rid = 1; 833 internal RID param_rid = 1; 834 internal RID property_rid = 1; 835 internal RID event_rid = 1; 836 internal RID local_variable_rid = 1; 837 internal RID local_constant_rid = 1; 838 839 readonly TypeRefTable type_ref_table; 840 readonly TypeDefTable type_def_table; 841 readonly FieldTable field_table; 842 readonly MethodTable method_table; 843 readonly ParamTable param_table; 844 readonly InterfaceImplTable iface_impl_table; 845 readonly MemberRefTable member_ref_table; 846 readonly ConstantTable constant_table; 847 readonly CustomAttributeTable custom_attribute_table; 848 readonly DeclSecurityTable declsec_table; 849 readonly StandAloneSigTable standalone_sig_table; 850 readonly EventMapTable event_map_table; 851 readonly EventTable event_table; 852 readonly PropertyMapTable property_map_table; 853 readonly PropertyTable property_table; 854 readonly TypeSpecTable typespec_table; 855 readonly MethodSpecTable method_spec_table; 856 857 internal MetadataBuilder metadata_builder; 858 859 readonly DocumentTable document_table; 860 readonly MethodDebugInformationTable method_debug_information_table; 861 readonly LocalScopeTable local_scope_table; 862 readonly LocalVariableTable local_variable_table; 863 readonly LocalConstantTable local_constant_table; 864 readonly ImportScopeTable import_scope_table; 865 readonly StateMachineMethodTable state_machine_method_table; 866 readonly CustomDebugInformationTable custom_debug_information_table; 867 868 readonly Dictionary<ImportScopeRow, MetadataToken> import_scope_map; 869 readonly Dictionary<string, MetadataToken> document_map; 870 871 public MetadataBuilder (ModuleDefinition module, string fq_name, uint timestamp, ISymbolWriterProvider symbol_writer_provider) 872 { 873 this.module = module; 874 this.text_map = CreateTextMap (); 875 this.fq_name = fq_name; 876 this.timestamp = timestamp; 877 this.symbol_writer_provider = symbol_writer_provider; 878 879 this.code = new CodeWriter (this); 880 this.data = new DataBuffer (); 881 this.resources = new ResourceBuffer (); 882 this.string_heap = new StringHeapBuffer (); 883 this.guid_heap = new GuidHeapBuffer (); 884 this.user_string_heap = new UserStringHeapBuffer (); 885 this.blob_heap = new BlobHeapBuffer (); 886 this.table_heap = new TableHeapBuffer (module, this); 887 888 this.type_ref_table = GetTable<TypeRefTable> (Table.TypeRef); 889 this.type_def_table = GetTable<TypeDefTable> (Table.TypeDef); 890 this.field_table = GetTable<FieldTable> (Table.Field); 891 this.method_table = GetTable<MethodTable> (Table.Method); 892 this.param_table = GetTable<ParamTable> (Table.Param); 893 this.iface_impl_table = GetTable<InterfaceImplTable> (Table.InterfaceImpl); 894 this.member_ref_table = GetTable<MemberRefTable> (Table.MemberRef); 895 this.constant_table = GetTable<ConstantTable> (Table.Constant); 896 this.custom_attribute_table = GetTable<CustomAttributeTable> (Table.CustomAttribute); 897 this.declsec_table = GetTable<DeclSecurityTable> (Table.DeclSecurity); 898 this.standalone_sig_table = GetTable<StandAloneSigTable> (Table.StandAloneSig); 899 this.event_map_table = GetTable<EventMapTable> (Table.EventMap); 900 this.event_table = GetTable<EventTable> (Table.Event); 901 this.property_map_table = GetTable<PropertyMapTable> (Table.PropertyMap); 902 this.property_table = GetTable<PropertyTable> (Table.Property); 903 this.typespec_table = GetTable<TypeSpecTable> (Table.TypeSpec); 904 this.method_spec_table = GetTable<MethodSpecTable> (Table.MethodSpec); 905 906 var row_equality_comparer = new RowEqualityComparer (); 907 type_ref_map = new Dictionary<TypeRefRow, MetadataToken> (row_equality_comparer); 908 type_spec_map = new Dictionary<uint, MetadataToken> (); 909 member_ref_map = new Dictionary<MemberRefRow, MetadataToken> (row_equality_comparer); 910 method_spec_map = new Dictionary<MethodSpecRow, MetadataToken> (row_equality_comparer); 911 generic_parameters = new Collection<GenericParameter> (); 912 913 this.document_table = GetTable<DocumentTable> (Table.Document); 914 this.method_debug_information_table = GetTable<MethodDebugInformationTable> (Table.MethodDebugInformation); 915 this.local_scope_table = GetTable<LocalScopeTable> (Table.LocalScope); 916 this.local_variable_table = GetTable<LocalVariableTable> (Table.LocalVariable); 917 this.local_constant_table = GetTable<LocalConstantTable> (Table.LocalConstant); 918 this.import_scope_table = GetTable<ImportScopeTable> (Table.ImportScope); 919 this.state_machine_method_table = GetTable<StateMachineMethodTable> (Table.StateMachineMethod); 920 this.custom_debug_information_table = GetTable<CustomDebugInformationTable> (Table.CustomDebugInformation); 921 922 this.document_map = new Dictionary<string, MetadataToken> (StringComparer.Ordinal); 923 this.import_scope_map = new Dictionary<ImportScopeRow, MetadataToken> (row_equality_comparer); 924 } 925 926 public MetadataBuilder (ModuleDefinition module, PortablePdbWriterProvider writer_provider) 927 { 928 this.module = module; 929 this.text_map = new TextMap (); 930 this.symbol_writer_provider = writer_provider; 931 932 this.string_heap = new StringHeapBuffer (); 933 this.guid_heap = new GuidHeapBuffer (); 934 this.user_string_heap = new UserStringHeapBuffer (); 935 this.blob_heap = new BlobHeapBuffer (); 936 this.table_heap = new TableHeapBuffer (module, this); 937 this.pdb_heap = new PdbHeapBuffer(); 938 939 this.document_table = GetTable<DocumentTable> (Table.Document); 940 this.method_debug_information_table = GetTable<MethodDebugInformationTable> (Table.MethodDebugInformation); 941 this.local_scope_table = GetTable<LocalScopeTable> (Table.LocalScope); 942 this.local_variable_table = GetTable<LocalVariableTable> (Table.LocalVariable); 943 this.local_constant_table = GetTable<LocalConstantTable> (Table.LocalConstant); 944 this.import_scope_table = GetTable<ImportScopeTable> (Table.ImportScope); 945 this.state_machine_method_table = GetTable<StateMachineMethodTable> (Table.StateMachineMethod); 946 this.custom_debug_information_table = GetTable<CustomDebugInformationTable> (Table.CustomDebugInformation); 947 948 var row_equality_comparer = new RowEqualityComparer (); 949 950 this.document_map = new Dictionary<string, MetadataToken> (); 951 this.import_scope_map = new Dictionary<ImportScopeRow, MetadataToken> (row_equality_comparer); 952 } 953 954 public void SetSymbolWriter (ISymbolWriter writer) 955 { 956 symbol_writer = writer; 957 958 if (symbol_writer == null && module.HasImage && module.Image.HasDebugTables ()) 959 symbol_writer = new PortablePdbWriter (this, module); 960 } 961 962 TextMap CreateTextMap () 963 { 964 var map = new TextMap (); 965 map.AddMap (TextSegment.ImportAddressTable, module.Architecture == TargetArchitecture.I386 ? 8 : 0); 966 map.AddMap (TextSegment.CLIHeader, 0x48, 8); 967 return map; 968 } 969 970 TTable GetTable<TTable> (Table table) where TTable : MetadataTable, new () 971 { 972 return table_heap.GetTable<TTable> (table); 973 } 974 975 uint GetStringIndex (string @string) 976 { 977 if (string.IsNullOrEmpty (@string)) 978 return 0; 979 980 return string_heap.GetStringIndex (@string); 981 } 982 983 uint GetGuidIndex (Guid guid) 984 { 985 return guid_heap.GetGuidIndex (guid); 986 } 987 988 uint GetBlobIndex (ByteBuffer blob) 989 { 990 if (blob.length == 0) 991 return 0; 992 993 return blob_heap.GetBlobIndex (blob); 994 } 995 996 uint GetBlobIndex (byte [] blob) 997 { 998 if (blob.IsNullOrEmpty ()) 999 return 0; 1000 1001 return GetBlobIndex (new ByteBuffer (blob)); 1002 } 1003 1004 public void BuildMetadata () 1005 { 1006 BuildModule (); 1007 1008 table_heap.string_offsets = string_heap.WriteStrings (); 1009 table_heap.ComputeTableInformations (); 1010 table_heap.WriteTableHeap (); 1011 } 1012 1013 void BuildModule () 1014 { 1015 var table = GetTable<ModuleTable> (Table.Module); 1016 table.row.Col1 = GetStringIndex (module.Name); 1017 table.row.Col2 = GetGuidIndex (module.Mvid); 1018 1019 var assembly = module.Assembly; 1020 1021 if (assembly != null) 1022 BuildAssembly (); 1023 1024 if (module.HasAssemblyReferences) 1025 AddAssemblyReferences (); 1026 1027 if (module.HasModuleReferences) 1028 AddModuleReferences (); 1029 1030 if (module.HasResources) 1031 AddResources (); 1032 1033 if (module.HasExportedTypes) 1034 AddExportedTypes (); 1035 1036 BuildTypes (); 1037 1038 if (assembly != null) { 1039 if (assembly.HasCustomAttributes) 1040 AddCustomAttributes (assembly); 1041 1042 if (assembly.HasSecurityDeclarations) 1043 AddSecurityDeclarations (assembly); 1044 } 1045 1046 if (module.HasCustomAttributes) 1047 AddCustomAttributes (module); 1048 1049 if (module.EntryPoint != null) 1050 entry_point = LookupToken (module.EntryPoint); 1051 } 1052 1053 void BuildAssembly () 1054 { 1055 var assembly = module.Assembly; 1056 var name = assembly.Name; 1057 1058 var table = GetTable<AssemblyTable> (Table.Assembly); 1059 1060 table.row = new AssemblyRow ( 1061 name.HashAlgorithm, 1062 (ushort) name.Version.Major, 1063 (ushort) name.Version.Minor, 1064 (ushort) name.Version.Build, 1065 (ushort) name.Version.Revision, 1066 name.Attributes, 1067 GetBlobIndex (name.PublicKey), 1068 GetStringIndex (name.Name), 1069 GetStringIndex (name.Culture)); 1070 1071 if (assembly.Modules.Count > 1) 1072 BuildModules (); 1073 } 1074 1075 void BuildModules () 1076 { 1077 var modules = this.module.Assembly.Modules; 1078 var table = GetTable<FileTable> (Table.File); 1079 1080 for (int i = 0; i < modules.Count; i++) { 1081 var module = modules [i]; 1082 if (module.IsMain) 1083 continue; 1084 1085#if NET_CORE 1086 throw new NotSupportedException (); 1087#else 1088 var parameters = new WriterParameters { 1089 SymbolWriterProvider = symbol_writer_provider, 1090 }; 1091 1092 var file_name = GetModuleFileName (module.Name); 1093 module.Write (file_name, parameters); 1094 1095 var hash = CryptoService.ComputeHash (file_name); 1096 1097 table.AddRow (new FileRow ( 1098 FileAttributes.ContainsMetaData, 1099 GetStringIndex (module.Name), 1100 GetBlobIndex (hash))); 1101#endif 1102 } 1103 } 1104 1105#if !NET_CORE 1106 string GetModuleFileName (string name) 1107 { 1108 if (string.IsNullOrEmpty (name)) 1109 throw new NotSupportedException (); 1110 1111 var path = Path.GetDirectoryName (fq_name); 1112 return Path.Combine (path, name); 1113 } 1114#endif 1115 1116 void AddAssemblyReferences () 1117 { 1118 var references = module.AssemblyReferences; 1119 var table = GetTable<AssemblyRefTable> (Table.AssemblyRef); 1120 1121 if (module.IsWindowsMetadata ()) 1122 module.Projections.RemoveVirtualReferences (references); 1123 1124 for (int i = 0; i < references.Count; i++) { 1125 var reference = references [i]; 1126 1127 var key_or_token = reference.PublicKey.IsNullOrEmpty () 1128 ? reference.PublicKeyToken 1129 : reference.PublicKey; 1130 1131 var version = reference.Version; 1132 1133 var rid = table.AddRow (new AssemblyRefRow ( 1134 (ushort) version.Major, 1135 (ushort) version.Minor, 1136 (ushort) version.Build, 1137 (ushort) version.Revision, 1138 reference.Attributes, 1139 GetBlobIndex (key_or_token), 1140 GetStringIndex (reference.Name), 1141 GetStringIndex (reference.Culture), 1142 GetBlobIndex (reference.Hash))); 1143 1144 reference.token = new MetadataToken (TokenType.AssemblyRef, rid); 1145 } 1146 1147 if (module.IsWindowsMetadata ()) 1148 module.Projections.AddVirtualReferences (references); 1149 } 1150 1151 void AddModuleReferences () 1152 { 1153 var references = module.ModuleReferences; 1154 var table = GetTable<ModuleRefTable> (Table.ModuleRef); 1155 1156 for (int i = 0; i < references.Count; i++) { 1157 var reference = references [i]; 1158 1159 reference.token = new MetadataToken ( 1160 TokenType.ModuleRef, 1161 table.AddRow (GetStringIndex (reference.Name))); 1162 } 1163 } 1164 1165 void AddResources () 1166 { 1167 var resources = module.Resources; 1168 var table = GetTable<ManifestResourceTable> (Table.ManifestResource); 1169 1170 for (int i = 0; i < resources.Count; i++) { 1171 var resource = resources [i]; 1172 1173 var row = new ManifestResourceRow ( 1174 0, 1175 resource.Attributes, 1176 GetStringIndex (resource.Name), 1177 0); 1178 1179 switch (resource.ResourceType) { 1180 case ResourceType.Embedded: 1181 row.Col1 = AddEmbeddedResource ((EmbeddedResource) resource); 1182 break; 1183 case ResourceType.Linked: 1184 row.Col4 = CodedIndex.Implementation.CompressMetadataToken ( 1185 new MetadataToken ( 1186 TokenType.File, 1187 AddLinkedResource ((LinkedResource) resource))); 1188 break; 1189 case ResourceType.AssemblyLinked: 1190 row.Col4 = CodedIndex.Implementation.CompressMetadataToken ( 1191 ((AssemblyLinkedResource) resource).Assembly.MetadataToken); 1192 break; 1193 default: 1194 throw new NotSupportedException (); 1195 } 1196 1197 table.AddRow (row); 1198 } 1199 } 1200 1201 uint AddLinkedResource (LinkedResource resource) 1202 { 1203 var table = GetTable<FileTable> (Table.File); 1204 var hash = resource.Hash; 1205 1206 if (hash.IsNullOrEmpty ()) 1207 hash = CryptoService.ComputeHash (resource.File); 1208 1209 return (uint) table.AddRow (new FileRow ( 1210 FileAttributes.ContainsNoMetaData, 1211 GetStringIndex (resource.File), 1212 GetBlobIndex (hash))); 1213 } 1214 1215 uint AddEmbeddedResource (EmbeddedResource resource) 1216 { 1217 return resources.AddResource (resource.GetResourceData ()); 1218 } 1219 1220 void AddExportedTypes () 1221 { 1222 var exported_types = module.ExportedTypes; 1223 var table = GetTable<ExportedTypeTable> (Table.ExportedType); 1224 1225 for (int i = 0; i < exported_types.Count; i++) { 1226 var exported_type = exported_types [i]; 1227 1228 var rid = table.AddRow (new ExportedTypeRow ( 1229 exported_type.Attributes, 1230 (uint) exported_type.Identifier, 1231 GetStringIndex (exported_type.Name), 1232 GetStringIndex (exported_type.Namespace), 1233 MakeCodedRID (GetExportedTypeScope (exported_type), CodedIndex.Implementation))); 1234 1235 exported_type.token = new MetadataToken (TokenType.ExportedType, rid); 1236 } 1237 } 1238 1239 MetadataToken GetExportedTypeScope (ExportedType exported_type) 1240 { 1241 if (exported_type.DeclaringType != null) 1242 return exported_type.DeclaringType.MetadataToken; 1243 1244 var scope = exported_type.Scope; 1245 switch (scope.MetadataToken.TokenType) { 1246 case TokenType.AssemblyRef: 1247 return scope.MetadataToken; 1248 case TokenType.ModuleRef: 1249 var file_table = GetTable<FileTable> (Table.File); 1250 for (int i = 0; i < file_table.length; i++) 1251 if (file_table.rows [i].Col2 == GetStringIndex (scope.Name)) 1252 return new MetadataToken (TokenType.File, i + 1); 1253 1254 break; 1255 } 1256 1257 throw new NotSupportedException (); 1258 } 1259 1260 void BuildTypes () 1261 { 1262 if (!module.HasTypes) 1263 return; 1264 1265 AttachTokens (); 1266 AddTypes (); 1267 AddGenericParameters (); 1268 } 1269 1270 void AttachTokens () 1271 { 1272 var types = module.Types; 1273 1274 for (int i = 0; i < types.Count; i++) 1275 AttachTypeToken (types [i]); 1276 } 1277 1278 void AttachTypeToken (TypeDefinition type) 1279 { 1280 type.token = new MetadataToken (TokenType.TypeDef, type_rid++); 1281 type.fields_range.Start = field_rid; 1282 type.methods_range.Start = method_rid; 1283 1284 if (type.HasFields) 1285 AttachFieldsToken (type); 1286 1287 if (type.HasMethods) 1288 AttachMethodsToken (type); 1289 1290 if (type.HasNestedTypes) 1291 AttachNestedTypesToken (type); 1292 } 1293 1294 void AttachNestedTypesToken (TypeDefinition type) 1295 { 1296 var nested_types = type.NestedTypes; 1297 for (int i = 0; i < nested_types.Count; i++) 1298 AttachTypeToken (nested_types [i]); 1299 } 1300 1301 void AttachFieldsToken (TypeDefinition type) 1302 { 1303 var fields = type.Fields; 1304 type.fields_range.Length = (uint) fields.Count; 1305 for (int i = 0; i < fields.Count; i++) 1306 fields [i].token = new MetadataToken (TokenType.Field, field_rid++); 1307 } 1308 1309 void AttachMethodsToken (TypeDefinition type) 1310 { 1311 var methods = type.Methods; 1312 type.methods_range.Length = (uint) methods.Count; 1313 for (int i = 0; i < methods.Count; i++) 1314 methods [i].token = new MetadataToken (TokenType.Method, method_rid++); 1315 } 1316 1317 MetadataToken GetTypeToken (TypeReference type) 1318 { 1319 if (type == null) 1320 return MetadataToken.Zero; 1321 1322 if (type.IsDefinition) 1323 return type.token; 1324 1325 if (type.IsTypeSpecification ()) 1326 return GetTypeSpecToken (type); 1327 1328 return GetTypeRefToken (type); 1329 } 1330 1331 MetadataToken GetTypeSpecToken (TypeReference type) 1332 { 1333 var row = GetBlobIndex (GetTypeSpecSignature (type)); 1334 1335 MetadataToken token; 1336 if (type_spec_map.TryGetValue (row, out token)) 1337 return token; 1338 1339 return AddTypeSpecification (type, row); 1340 } 1341 1342 MetadataToken AddTypeSpecification (TypeReference type, uint row) 1343 { 1344 type.token = new MetadataToken (TokenType.TypeSpec, typespec_table.AddRow (row)); 1345 1346 var token = type.token; 1347 type_spec_map.Add (row, token); 1348 return token; 1349 } 1350 1351 MetadataToken GetTypeRefToken (TypeReference type) 1352 { 1353 var projection = WindowsRuntimeProjections.RemoveProjection (type); 1354 1355 var row = CreateTypeRefRow (type); 1356 1357 MetadataToken token; 1358 if (!type_ref_map.TryGetValue (row, out token)) 1359 token = AddTypeReference (type, row); 1360 1361 WindowsRuntimeProjections.ApplyProjection (type, projection); 1362 1363 return token; 1364 } 1365 1366 TypeRefRow CreateTypeRefRow (TypeReference type) 1367 { 1368 var scope_token = GetScopeToken (type); 1369 1370 return new TypeRefRow ( 1371 MakeCodedRID (scope_token, CodedIndex.ResolutionScope), 1372 GetStringIndex (type.Name), 1373 GetStringIndex (type.Namespace)); 1374 } 1375 1376 MetadataToken GetScopeToken (TypeReference type) 1377 { 1378 if (type.IsNested) 1379 return GetTypeRefToken (type.DeclaringType); 1380 1381 var scope = type.Scope; 1382 1383 if (scope == null) 1384 return MetadataToken.Zero; 1385 1386 return scope.MetadataToken; 1387 } 1388 1389 static CodedRID MakeCodedRID (IMetadataTokenProvider provider, CodedIndex index) 1390 { 1391 return MakeCodedRID (provider.MetadataToken, index); 1392 } 1393 1394 static CodedRID MakeCodedRID (MetadataToken token, CodedIndex index) 1395 { 1396 return index.CompressMetadataToken (token); 1397 } 1398 1399 MetadataToken AddTypeReference (TypeReference type, TypeRefRow row) 1400 { 1401 type.token = new MetadataToken (TokenType.TypeRef, type_ref_table.AddRow (row)); 1402 1403 var token = type.token; 1404 type_ref_map.Add (row, token); 1405 return token; 1406 } 1407 1408 void AddTypes () 1409 { 1410 var types = module.Types; 1411 1412 for (int i = 0; i < types.Count; i++) 1413 AddType (types [i]); 1414 } 1415 1416 void AddType (TypeDefinition type) 1417 { 1418 var treatment = WindowsRuntimeProjections.RemoveProjection (type); 1419 1420 type_def_table.AddRow (new TypeDefRow ( 1421 type.Attributes, 1422 GetStringIndex (type.Name), 1423 GetStringIndex (type.Namespace), 1424 MakeCodedRID (GetTypeToken (type.BaseType), CodedIndex.TypeDefOrRef), 1425 type.fields_range.Start, 1426 type.methods_range.Start)); 1427 1428 if (type.HasGenericParameters) 1429 AddGenericParameters (type); 1430 1431 if (type.HasInterfaces) 1432 AddInterfaces (type); 1433 1434 AddLayoutInfo (type); 1435 1436 if (type.HasFields) 1437 AddFields (type); 1438 1439 if (type.HasMethods) 1440 AddMethods (type); 1441 1442 if (type.HasProperties) 1443 AddProperties (type); 1444 1445 if (type.HasEvents) 1446 AddEvents (type); 1447 1448 if (type.HasCustomAttributes) 1449 AddCustomAttributes (type); 1450 1451 if (type.HasSecurityDeclarations) 1452 AddSecurityDeclarations (type); 1453 1454 if (type.HasNestedTypes) 1455 AddNestedTypes (type); 1456 1457 WindowsRuntimeProjections.ApplyProjection (type, treatment); 1458 } 1459 1460 void AddGenericParameters (IGenericParameterProvider owner) 1461 { 1462 var parameters = owner.GenericParameters; 1463 1464 for (int i = 0; i < parameters.Count; i++) 1465 generic_parameters.Add (parameters [i]); 1466 } 1467 1468 sealed class GenericParameterComparer : IComparer<GenericParameter> { 1469 1470 public int Compare (GenericParameter a, GenericParameter b) 1471 { 1472 var a_owner = MakeCodedRID (a.Owner, CodedIndex.TypeOrMethodDef); 1473 var b_owner = MakeCodedRID (b.Owner, CodedIndex.TypeOrMethodDef); 1474 if (a_owner == b_owner) { 1475 var a_pos = a.Position; 1476 var b_pos = b.Position; 1477 return a_pos == b_pos ? 0 : a_pos > b_pos ? 1 : -1; 1478 } 1479 1480 return a_owner > b_owner ? 1 : -1; 1481 } 1482 } 1483 1484 void AddGenericParameters () 1485 { 1486 var items = this.generic_parameters.items; 1487 var size = this.generic_parameters.size; 1488 Array.Sort (items, 0, size, new GenericParameterComparer ()); 1489 1490 var generic_param_table = GetTable<GenericParamTable> (Table.GenericParam); 1491 var generic_param_constraint_table = GetTable<GenericParamConstraintTable> (Table.GenericParamConstraint); 1492 1493 for (int i = 0; i < size; i++) { 1494 var generic_parameter = items [i]; 1495 1496 var rid = generic_param_table.AddRow (new GenericParamRow ( 1497 (ushort) generic_parameter.Position, 1498 generic_parameter.Attributes, 1499 MakeCodedRID (generic_parameter.Owner, CodedIndex.TypeOrMethodDef), 1500 GetStringIndex (generic_parameter.Name))); 1501 1502 generic_parameter.token = new MetadataToken (TokenType.GenericParam, rid); 1503 1504 if (generic_parameter.HasConstraints) 1505 AddConstraints (generic_parameter, generic_param_constraint_table); 1506 1507 if (generic_parameter.HasCustomAttributes) 1508 AddCustomAttributes (generic_parameter); 1509 } 1510 } 1511 1512 void AddConstraints (GenericParameter generic_parameter, GenericParamConstraintTable table) 1513 { 1514 var constraints = generic_parameter.Constraints; 1515 1516 var gp_rid = generic_parameter.token.RID; 1517 1518 for (int i = 0; i < constraints.Count; i++) { 1519 var constraint = constraints [i]; 1520 1521 var rid = table.AddRow (new GenericParamConstraintRow ( 1522 gp_rid, 1523 MakeCodedRID (GetTypeToken (constraint.ConstraintType), CodedIndex.TypeDefOrRef))); 1524 1525 constraint.token = new MetadataToken (TokenType.GenericParamConstraint, rid); 1526 1527 if (constraint.HasCustomAttributes) 1528 AddCustomAttributes (constraint); 1529 } 1530 } 1531 1532 void AddInterfaces (TypeDefinition type) 1533 { 1534 var interfaces = type.Interfaces; 1535 var type_rid = type.token.RID; 1536 1537 for (int i = 0; i < interfaces.Count; i++) { 1538 var iface_impl = interfaces [i]; 1539 1540 var rid = iface_impl_table.AddRow (new InterfaceImplRow ( 1541 type_rid, 1542 MakeCodedRID (GetTypeToken (iface_impl.InterfaceType), CodedIndex.TypeDefOrRef))); 1543 1544 iface_impl.token = new MetadataToken (TokenType.InterfaceImpl, rid); 1545 1546 if (iface_impl.HasCustomAttributes) 1547 AddCustomAttributes (iface_impl); 1548 } 1549 } 1550 1551 void AddLayoutInfo (TypeDefinition type) 1552 { 1553 if (type.HasLayoutInfo) { 1554 var table = GetTable<ClassLayoutTable> (Table.ClassLayout); 1555 1556 table.AddRow (new ClassLayoutRow ( 1557 (ushort) type.PackingSize, 1558 (uint) type.ClassSize, 1559 type.token.RID)); 1560 1561 return; 1562 } 1563 1564 if (type.IsValueType && HasNoInstanceField (type)) { 1565 var table = GetTable<ClassLayoutTable> (Table.ClassLayout); 1566 1567 table.AddRow (new ClassLayoutRow (0, 1, type.token.RID)); 1568 } 1569 } 1570 1571 static bool HasNoInstanceField (TypeDefinition type) 1572 { 1573 if (!type.HasFields) 1574 return true; 1575 1576 var fields = type.Fields; 1577 1578 for (int i = 0; i < fields.Count; i++) 1579 if (!fields [i].IsStatic) 1580 return false; 1581 1582 return true; 1583 } 1584 1585 void AddNestedTypes (TypeDefinition type) 1586 { 1587 var nested_types = type.NestedTypes; 1588 var nested_table = GetTable<NestedClassTable> (Table.NestedClass); 1589 1590 for (int i = 0; i < nested_types.Count; i++) { 1591 var nested = nested_types [i]; 1592 AddType (nested); 1593 nested_table.AddRow (new NestedClassRow (nested.token.RID, type.token.RID)); 1594 } 1595 } 1596 1597 void AddFields (TypeDefinition type) 1598 { 1599 var fields = type.Fields; 1600 1601 for (int i = 0; i < fields.Count; i++) 1602 AddField (fields [i]); 1603 } 1604 1605 void AddField (FieldDefinition field) 1606 { 1607 var projection = WindowsRuntimeProjections.RemoveProjection (field); 1608 1609 field_table.AddRow (new FieldRow ( 1610 field.Attributes, 1611 GetStringIndex (field.Name), 1612 GetBlobIndex (GetFieldSignature (field)))); 1613 1614 if (!field.InitialValue.IsNullOrEmpty ()) 1615 AddFieldRVA (field); 1616 1617 if (field.HasLayoutInfo) 1618 AddFieldLayout (field); 1619 1620 if (field.HasCustomAttributes) 1621 AddCustomAttributes (field); 1622 1623 if (field.HasConstant) 1624 AddConstant (field, field.FieldType); 1625 1626 if (field.HasMarshalInfo) 1627 AddMarshalInfo (field); 1628 1629 WindowsRuntimeProjections.ApplyProjection (field, projection); 1630 } 1631 1632 void AddFieldRVA (FieldDefinition field) 1633 { 1634 var table = GetTable<FieldRVATable> (Table.FieldRVA); 1635 table.AddRow (new FieldRVARow ( 1636 data.AddData (field.InitialValue), 1637 field.token.RID)); 1638 } 1639 1640 void AddFieldLayout (FieldDefinition field) 1641 { 1642 var table = GetTable<FieldLayoutTable> (Table.FieldLayout); 1643 table.AddRow (new FieldLayoutRow ((uint) field.Offset, field.token.RID)); 1644 } 1645 1646 void AddMethods (TypeDefinition type) 1647 { 1648 var methods = type.Methods; 1649 1650 for (int i = 0; i < methods.Count; i++) 1651 AddMethod (methods [i]); 1652 } 1653 1654 void AddMethod (MethodDefinition method) 1655 { 1656 var projection = WindowsRuntimeProjections.RemoveProjection (method); 1657 1658 method_table.AddRow (new MethodRow ( 1659 method.HasBody ? code.WriteMethodBody (method) : 0, 1660 method.ImplAttributes, 1661 method.Attributes, 1662 GetStringIndex (method.Name), 1663 GetBlobIndex (GetMethodSignature (method)), 1664 param_rid)); 1665 1666 AddParameters (method); 1667 1668 if (method.HasGenericParameters) 1669 AddGenericParameters (method); 1670 1671 if (method.IsPInvokeImpl) 1672 AddPInvokeInfo (method); 1673 1674 if (method.HasCustomAttributes) 1675 AddCustomAttributes (method); 1676 1677 if (method.HasSecurityDeclarations) 1678 AddSecurityDeclarations (method); 1679 1680 if (method.HasOverrides) 1681 AddOverrides (method); 1682 1683 WindowsRuntimeProjections.ApplyProjection (method, projection); 1684 } 1685 1686 void AddParameters (MethodDefinition method) 1687 { 1688 var return_parameter = method.MethodReturnType.parameter; 1689 1690 if (return_parameter != null && RequiresParameterRow (return_parameter)) 1691 AddParameter (0, return_parameter, param_table); 1692 1693 if (!method.HasParameters) 1694 return; 1695 1696 var parameters = method.Parameters; 1697 1698 for (int i = 0; i < parameters.Count; i++) { 1699 var parameter = parameters [i]; 1700 if (!RequiresParameterRow (parameter)) 1701 continue; 1702 1703 AddParameter ((ushort) (i + 1), parameter, param_table); 1704 } 1705 } 1706 1707 v…
Large files files are truncated, but you can click here to view the full file