5 // Jb Evain (jbevain@gmail.com)
7 // Copyright (c) 2008 - 2010 Jb Evain
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using Mono.Cecil.Metadata;
37 using RVA = System.UInt32;
39 namespace Mono.Cecil.PE {
41 sealed class ImageWriter : BinaryStreamWriter {
43 readonly ModuleDefinition module;
44 readonly MetadataBuilder metadata;
45 readonly TextMap text_map;
47 ImageDebugDirectory debug_directory;
50 ByteBuffer win32_resources;
52 const uint pe_header_size = 0x178u;
53 const uint section_header_size = 0x28u;
54 const uint file_alignment = 0x200;
55 const uint section_alignment = 0x2000;
56 const ulong image_base = 0x00400000;
58 internal const RVA text_rva = 0x2000;
61 readonly uint time_stamp;
63 internal Section text;
64 internal Section rsrc;
65 internal Section reloc;
69 ImageWriter (ModuleDefinition module, MetadataBuilder metadata, Stream stream)
73 this.metadata = metadata;
74 this.GetDebugHeader ();
75 this.GetWin32Resources ();
76 this.text_map = BuildTextMap ();
77 this.sections = 2; // text + reloc
78 this.pe64 = module.Architecture != TargetArchitecture.I386;
79 this.time_stamp = (uint) DateTime.UtcNow.Subtract (new DateTime (1970, 1, 1)).TotalSeconds;
82 void GetDebugHeader ()
84 var symbol_writer = metadata.symbol_writer;
85 if (symbol_writer == null)
88 if (!symbol_writer.GetDebugHeader (out debug_directory, out debug_data))
89 debug_data = Empty<byte>.Array;
92 void GetWin32Resources ()
94 var rsrc = GetImageResourceSection ();
98 var raw_resources = new byte [rsrc.Data.Length];
99 Buffer.BlockCopy (rsrc.Data, 0, raw_resources, 0, rsrc.Data.Length);
100 win32_resources = new ByteBuffer (raw_resources);
103 Section GetImageResourceSection ()
105 if (!module.HasImage)
108 const string rsrc_section = ".rsrc";
110 return module.Image.GetSection (rsrc_section);
113 public static ImageWriter CreateWriter (ModuleDefinition module, MetadataBuilder metadata, Stream stream)
115 var writer = new ImageWriter (module, metadata, stream);
116 writer.BuildSections ();
120 void BuildSections ()
122 var has_win32_resources = win32_resources != null;
123 if (has_win32_resources)
126 text = CreateSection (".text", text_map.GetLength (), null);
129 if (has_win32_resources) {
130 rsrc = CreateSection (".rsrc", (uint) win32_resources.length, previous);
132 PatchWin32Resources (win32_resources);
136 reloc = CreateSection (".reloc", 12u, previous);
139 Section CreateSection (string name, uint size, Section previous)
143 VirtualAddress = previous != null
144 ? previous.VirtualAddress + Align (previous.VirtualSize, section_alignment)
147 PointerToRawData = previous != null
148 ? previous.PointerToRawData + previous.SizeOfRawData
149 : Align (GetHeaderSize (), file_alignment),
150 SizeOfRawData = Align (size, file_alignment)
154 static uint Align (uint value, uint align)
157 return (value + align) & ~align;
160 void WriteDOSHeader ()
164 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00,
165 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff,
166 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00,
167 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
172 0x00, 0x00, 0x00, 0x00,
174 0x80, 0x00, 0x00, 0x00,
176 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09,
177 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21,
178 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72,
179 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63,
180 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62,
181 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69,
182 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20, 0x6d,
183 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,
184 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189 void WritePEFileHeader ()
191 WriteUInt32 (0x00004550); // Magic
192 WriteUInt16 (GetMachine ()); // Machine
193 WriteUInt16 (sections); // NumberOfSections
194 WriteUInt32 (time_stamp);
195 WriteUInt32 (0); // PointerToSymbolTable
196 WriteUInt32 (0); // NumberOfSymbols
197 WriteUInt16 ((ushort) (!pe64 ? 0xe0 : 0xf0)); // SizeOfOptionalHeader
199 // ExecutableImage | (pe64 ? 32BitsMachine : LargeAddressAware)
200 var characteristics = (ushort) (0x0002 | (!pe64 ? 0x0100 : 0x0020));
201 if (module.Kind == ModuleKind.Dll || module.Kind == ModuleKind.NetModule)
202 characteristics |= 0x2000;
203 WriteUInt16 (characteristics); // Characteristics
208 switch (module.Architecture) {
209 case TargetArchitecture.I386:
211 case TargetArchitecture.AMD64:
213 case TargetArchitecture.IA64:
217 throw new NotSupportedException ();
220 void WriteOptionalHeaders ()
222 WriteUInt16 ((ushort) (!pe64 ? 0x10b : 0x20b)); // Magic
223 WriteByte (8); // LMajor
224 WriteByte (0); // LMinor
225 WriteUInt32 (text.SizeOfRawData); // CodeSize
226 WriteUInt32 (reloc.SizeOfRawData
227 + (rsrc != null ? rsrc.SizeOfRawData : 0)); // InitializedDataSize
228 WriteUInt32 (0); // UninitializedDataSize
230 var entry_point_rva = text_map.GetRVA (TextSegment.StartupStub);
231 if (module.Architecture == TargetArchitecture.IA64)
232 entry_point_rva += 0x20;
233 WriteUInt32 (entry_point_rva); // EntryPointRVA
234 WriteUInt32 (text_rva); // BaseOfCode
237 WriteUInt32 (0); // BaseOfData
238 WriteUInt32 ((uint) image_base); // ImageBase
240 WriteUInt64 (image_base); // ImageBase
243 WriteUInt32 (section_alignment); // SectionAlignment
244 WriteUInt32 (file_alignment); // FileAlignment
246 WriteUInt16 (4); // OSMajor
247 WriteUInt16 (0); // OSMinor
248 WriteUInt16 (0); // UserMajor
249 WriteUInt16 (0); // UserMinor
250 WriteUInt16 (4); // SubSysMajor
251 WriteUInt16 (0); // SubSysMinor
252 WriteUInt32 (0); // Reserved
254 WriteUInt32 (reloc.VirtualAddress + Align (reloc.VirtualSize, section_alignment)); // ImageSize
255 WriteUInt32 (text.PointerToRawData); // HeaderSize
257 WriteUInt32 (0); // Checksum
258 WriteUInt16 (GetSubSystem ()); // SubSystem
259 WriteUInt16 (0x8540); // DLLFlags
261 const ulong stack_reserve = 0x100000;
262 const ulong stack_commit = 0x1000;
263 const ulong heap_reserve = 0x100000;
264 const ulong heap_commit = 0x1000;
267 WriteUInt32 ((uint) stack_reserve);
268 WriteUInt32 ((uint) stack_commit);
269 WriteUInt32 ((uint) heap_reserve);
270 WriteUInt32 ((uint) heap_commit);
272 WriteUInt64 (stack_reserve);
273 WriteUInt64 (stack_commit);
274 WriteUInt64 (heap_reserve);
275 WriteUInt64 (heap_commit);
278 WriteUInt32 (0); // LoaderFlags
279 WriteUInt32 (16); // NumberOfDataDir
281 WriteZeroDataDirectory (); // ExportTable
282 WriteDataDirectory (text_map.GetDataDirectory (TextSegment.ImportDirectory)); // ImportTable
283 if (rsrc != null) { // ResourceTable
284 WriteUInt32 (rsrc.VirtualAddress);
285 WriteUInt32 (rsrc.VirtualSize);
287 WriteZeroDataDirectory ();
289 WriteZeroDataDirectory (); // ExceptionTable
290 WriteZeroDataDirectory (); // CertificateTable
291 WriteUInt32 (reloc.VirtualAddress); // BaseRelocationTable
292 WriteUInt32 (reloc.VirtualSize);
294 if (text_map.GetLength (TextSegment.DebugDirectory) > 0) {
295 WriteUInt32 (text_map.GetRVA (TextSegment.DebugDirectory));
298 WriteZeroDataDirectory ();
300 WriteZeroDataDirectory (); // Copyright
301 WriteZeroDataDirectory (); // GlobalPtr
302 WriteZeroDataDirectory (); // TLSTable
303 WriteZeroDataDirectory (); // LoadConfigTable
304 WriteZeroDataDirectory (); // BoundImport
305 WriteDataDirectory (text_map.GetDataDirectory (TextSegment.ImportAddressTable)); // IAT
306 WriteZeroDataDirectory (); // DelayImportDesc
307 WriteDataDirectory (text_map.GetDataDirectory (TextSegment.CLIHeader)); // CLIHeader
308 WriteZeroDataDirectory (); // Reserved
311 void WriteZeroDataDirectory ()
317 ushort GetSubSystem ()
319 switch (module.Kind) {
320 case ModuleKind.Console:
322 case ModuleKind.NetModule:
324 case ModuleKind.Windows:
327 throw new ArgumentOutOfRangeException ();
331 void WriteSectionHeaders ()
333 WriteSection (text, 0x60000020);
336 WriteSection (rsrc, 0x40000040);
338 WriteSection (reloc, 0x42000040);
341 void WriteSection (Section section, uint characteristics)
343 var name = new byte [8];
344 var sect_name = section.Name;
345 for (int i = 0; i < sect_name.Length; i++)
346 name [i] = (byte) sect_name [i];
349 WriteUInt32 (section.VirtualSize);
350 WriteUInt32 (section.VirtualAddress);
351 WriteUInt32 (section.SizeOfRawData);
352 WriteUInt32 (section.PointerToRawData);
353 WriteUInt32 (0); // PointerToRelocations
354 WriteUInt32 (0); // PointerToLineNumbers
355 WriteUInt16 (0); // NumberOfRelocations
356 WriteUInt16 (0); // NumberOfLineNumbers
357 WriteUInt32 (characteristics);
360 void MoveTo (uint pointer)
362 BaseStream.Seek (pointer, SeekOrigin.Begin);
365 void MoveToRVA (Section section, RVA rva)
367 BaseStream.Seek (section.PointerToRawData + rva - section.VirtualAddress, SeekOrigin.Begin);
370 void MoveToRVA (TextSegment segment)
372 MoveToRVA (text, text_map.GetRVA (segment));
375 void WriteRVA (RVA rva)
385 MoveTo (text.PointerToRawData);
387 // ImportAddressTable
389 WriteRVA (text_map.GetRVA (TextSegment.ImportHintNameTable));
396 WriteUInt16 ((ushort) ((module.Runtime <= TargetRuntime.Net_1_1) ? 0 : 5));
398 WriteUInt32 (text_map.GetRVA (TextSegment.MetadataHeader));
399 WriteUInt32 (GetMetadataLength ());
400 WriteUInt32 ((uint) module.Attributes);
401 WriteUInt32 (metadata.entry_point.ToUInt32 ());
402 WriteDataDirectory (text_map.GetDataDirectory (TextSegment.Resources));
403 WriteDataDirectory (text_map.GetDataDirectory (TextSegment.StrongNameSignature));
404 WriteZeroDataDirectory (); // CodeManagerTable
405 WriteZeroDataDirectory (); // VTableFixups
406 WriteZeroDataDirectory (); // ExportAddressTableJumps
407 WriteZeroDataDirectory (); // ManagedNativeHeader
411 MoveToRVA (TextSegment.Code);
412 WriteBuffer (metadata.code);
416 MoveToRVA (TextSegment.Resources);
417 WriteBuffer (metadata.resources);
421 if (metadata.data.length > 0) {
422 MoveToRVA (TextSegment.Data);
423 WriteBuffer (metadata.data);
426 // StrongNameSignature
431 MoveToRVA (TextSegment.MetadataHeader);
432 WriteMetadataHeader ();
437 if (text_map.GetLength (TextSegment.DebugDirectory) > 0) {
438 MoveToRVA (TextSegment.DebugDirectory);
439 WriteDebugDirectory ();
443 MoveToRVA (TextSegment.ImportDirectory);
444 WriteImportDirectory ();
447 MoveToRVA (TextSegment.StartupStub);
451 uint GetMetadataLength ()
453 return text_map.GetRVA (TextSegment.DebugDirectory) - text_map.GetRVA (TextSegment.MetadataHeader);
456 void WriteMetadataHeader ()
458 WriteUInt32 (0x424a5342); // Signature
459 WriteUInt16 (1); // MajorVersion
460 WriteUInt16 (1); // MinorVersion
461 WriteUInt32 (0); // Reserved
463 var version = GetZeroTerminatedString (GetVersion ());
464 WriteUInt32 ((uint) version.Length);
465 WriteBytes (version);
466 WriteUInt16 (0); // Flags
467 WriteUInt16 (GetStreamCount ());
469 uint offset = text_map.GetRVA (TextSegment.TableHeap) - text_map.GetRVA (TextSegment.MetadataHeader);
471 WriteStreamHeader (ref offset, TextSegment.TableHeap, "#~");
472 WriteStreamHeader (ref offset, TextSegment.StringHeap, "#Strings");
473 WriteStreamHeader (ref offset, TextSegment.UserStringHeap, "#US");
474 WriteStreamHeader (ref offset, TextSegment.GuidHeap, "#GUID");
475 WriteStreamHeader (ref offset, TextSegment.BlobHeap, "#Blob");
480 switch (module.Runtime) {
481 case TargetRuntime.Net_1_0:
483 case TargetRuntime.Net_1_1:
485 case TargetRuntime.Net_2_0:
487 case TargetRuntime.Net_4_0:
493 ushort GetStreamCount ()
498 + (metadata.user_string_heap.IsEmpty ? 0 : 1) // #US
500 + (metadata.blob_heap.IsEmpty ? 0 : 1)); // #Blob
503 void WriteStreamHeader (ref uint offset, TextSegment heap, string name)
505 var length = (uint) text_map.GetLength (heap);
509 WriteUInt32 (offset);
510 WriteUInt32 (length);
511 WriteBytes (GetZeroTerminatedString (name));
515 static byte [] GetZeroTerminatedString (string @string)
517 return GetString (@string, (@string.Length + 1 + 3) & ~3);
520 static byte [] GetSimpleString (string @string)
522 return GetString (@string, @string.Length);
525 static byte [] GetString (string @string, int length)
527 var bytes = new byte [length];
528 for (int i = 0; i < @string.Length; i++)
529 bytes [i] = (byte) @string [i];
534 void WriteMetadata ()
536 WriteHeap (TextSegment.TableHeap, metadata.table_heap);
537 WriteHeap (TextSegment.StringHeap, metadata.string_heap);
538 WriteHeap (TextSegment.UserStringHeap, metadata.user_string_heap);
540 WriteHeap (TextSegment.BlobHeap, metadata.blob_heap);
543 void WriteHeap (TextSegment heap, HeapBuffer buffer)
549 WriteBuffer (buffer);
552 void WriteGuidHeap ()
554 MoveToRVA (TextSegment.GuidHeap);
555 WriteBytes (module.Mvid.ToByteArray ());
558 void WriteDebugDirectory ()
560 WriteInt32 (debug_directory.Characteristics);
561 WriteUInt32 (time_stamp);
562 WriteInt16 (debug_directory.MajorVersion);
563 WriteInt16 (debug_directory.MinorVersion);
564 WriteInt32 (debug_directory.Type);
565 WriteInt32 (debug_directory.SizeOfData);
566 WriteInt32 (debug_directory.AddressOfRawData);
567 WriteInt32 ((int) BaseStream.Position + 4);
569 WriteBytes (debug_data);
572 void WriteImportDirectory ()
574 WriteUInt32 (text_map.GetRVA (TextSegment.ImportDirectory) + 40); // ImportLookupTable
575 WriteUInt32 (0); // DateTimeStamp
576 WriteUInt32 (0); // ForwarderChain
577 WriteUInt32 (text_map.GetRVA (TextSegment.ImportHintNameTable) + 14);
578 WriteUInt32 (text_map.GetRVA (TextSegment.ImportAddressTable));
582 WriteUInt32 (text_map.GetRVA (TextSegment.ImportHintNameTable));
584 // ImportHintNameTable
585 MoveToRVA (TextSegment.ImportHintNameTable);
587 WriteUInt16 (0); // Hint
588 WriteBytes (GetRuntimeMain ());
590 WriteBytes (GetSimpleString ("mscoree.dll"));
594 byte [] GetRuntimeMain ()
596 return module.Kind == ModuleKind.Dll || module.Kind == ModuleKind.NetModule
597 ? GetSimpleString ("_CorDllMain")
598 : GetSimpleString ("_CorExeMain");
601 void WriteStartupStub ()
603 switch (module.Architecture) {
604 case TargetArchitecture.I386:
605 WriteUInt16 (0x25ff);
606 WriteUInt32 ((uint) image_base + text_map.GetRVA (TextSegment.ImportAddressTable));
608 case TargetArchitecture.AMD64:
609 WriteUInt16 (0xa148);
610 WriteUInt32 ((uint) image_base + text_map.GetRVA (TextSegment.ImportAddressTable));
611 WriteUInt16 (0xe0ff);
613 case TargetArchitecture.IA64:
614 WriteBytes (new byte [] {
615 0x0b, 0x48, 0x00, 0x02, 0x18, 0x10, 0xa0, 0x40, 0x24, 0x30, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00,
616 0x10, 0x08, 0x00, 0x12, 0x18, 0x10, 0x60, 0x50, 0x04, 0x80, 0x03, 0x00, 0x60, 0x00, 0x80, 0x00
618 WriteUInt32 ((uint) image_base + text_map.GetRVA (TextSegment.StartupStub));
619 WriteUInt32 ((uint) image_base + text_rva);
626 MoveTo (rsrc.PointerToRawData);
627 WriteBuffer (win32_resources);
632 MoveTo (reloc.PointerToRawData);
634 var reloc_rva = text_map.GetRVA (TextSegment.StartupStub);
635 reloc_rva += module.Architecture == TargetArchitecture.IA64 ? 0x20u : 2;
636 var page_rva = reloc_rva & ~0xfffu;
638 WriteUInt32 (page_rva); // PageRVA
639 WriteUInt32 (0x000c); // Block Size
641 switch (module.Architecture) {
642 case TargetArchitecture.I386:
643 WriteUInt32 (0x3000 + reloc_rva - page_rva);
645 case TargetArchitecture.AMD64:
646 WriteUInt32 (0xa000 + reloc_rva - page_rva);
648 case TargetArchitecture.IA64:
649 WriteUInt16 ((ushort) (0xa000 + reloc_rva - page_rva));
650 WriteUInt16 ((ushort) (0xa000 + reloc_rva - page_rva + 8));
654 WriteBytes (new byte [file_alignment - reloc.VirtualSize]);
657 public void WriteImage ()
660 WritePEFileHeader ();
661 WriteOptionalHeaders ();
662 WriteSectionHeaders ();
669 TextMap BuildTextMap ()
671 var map = metadata.text_map;
673 map.AddMap (TextSegment.Code, metadata.code.length, !pe64 ? 4 : 16);
674 map.AddMap (TextSegment.Resources, metadata.resources.length, 8);
675 map.AddMap (TextSegment.Data, metadata.data.length, 4);
676 if (metadata.data.length > 0)
677 metadata.table_heap.FixupData (map.GetRVA (TextSegment.Data));
678 map.AddMap (TextSegment.StrongNameSignature, GetStrongNameLength (), 4);
680 map.AddMap (TextSegment.MetadataHeader, GetMetadataHeaderLength ());
681 map.AddMap (TextSegment.TableHeap, metadata.table_heap.length, 4);
682 map.AddMap (TextSegment.StringHeap, metadata.string_heap.length, 4);
683 map.AddMap (TextSegment.UserStringHeap, metadata.user_string_heap.IsEmpty ? 0 : metadata.user_string_heap.length, 4);
684 map.AddMap (TextSegment.GuidHeap, 16);
685 map.AddMap (TextSegment.BlobHeap, metadata.blob_heap.IsEmpty ? 0 : metadata.blob_heap.length, 4);
687 int debug_dir_len = 0;
688 if (!debug_data.IsNullOrEmpty ()) {
689 const int debug_dir_header_len = 28;
691 debug_directory.AddressOfRawData = (int) map.GetNextRVA (TextSegment.BlobHeap) + debug_dir_header_len;
692 debug_dir_len = debug_data.Length + debug_dir_header_len;
695 map.AddMap (TextSegment.DebugDirectory, debug_dir_len, 4);
697 RVA import_dir_rva = map.GetNextRVA (TextSegment.DebugDirectory);
698 RVA import_hnt_rva = import_dir_rva + (!pe64 ? 48u : 52u);
699 import_hnt_rva = (import_hnt_rva + 15u) & ~15u;
700 uint import_dir_len = (import_hnt_rva - import_dir_rva) + 27u;
702 RVA startup_stub_rva = import_dir_rva + import_dir_len;
703 startup_stub_rva = module.Architecture == TargetArchitecture.IA64
704 ? (startup_stub_rva + 15u) & ~15u
705 : 2 + ((startup_stub_rva + 3u) & ~3u);
707 map.AddMap (TextSegment.ImportDirectory, new Range (import_dir_rva, import_dir_len));
708 map.AddMap (TextSegment.ImportHintNameTable, new Range (import_hnt_rva, 0));
709 map.AddMap (TextSegment.StartupStub, new Range (startup_stub_rva, GetStartupStubLength ()));
714 uint GetStartupStubLength ()
716 switch (module.Architecture) {
717 case TargetArchitecture.I386:
719 case TargetArchitecture.AMD64:
721 case TargetArchitecture.IA64:
724 throw new InvalidOperationException ();
728 int GetMetadataHeaderLength ()
738 + (metadata.user_string_heap.IsEmpty ? 0 : 12)
742 + (metadata.blob_heap.IsEmpty ? 0 : 16);
745 int GetStrongNameLength ()
747 if ((module.Attributes & ModuleAttributes.StrongNameSigned) == 0)
750 if (module.Assembly == null)
751 throw new InvalidOperationException ();
753 var public_key = module.Assembly.Name.PublicKey;
755 if (public_key != null) {
756 // in fx 2.0 the key may be from 384 to 16384 bits
757 // so we must calculate the signature size based on
758 // the size of the public key (minus the 32 byte header)
759 int size = public_key.Length;
762 // note: size == 16 for the ECMA "key" which is replaced
763 // by the runtime with a 1024 bits key (128 bytes)
766 return 128; // default strongname signature size
769 public DataDirectory GetStrongNameSignatureDirectory ()
771 return text_map.GetDataDirectory (TextSegment.StrongNameSignature);
774 public uint GetHeaderSize ()
776 return pe_header_size + (sections * section_header_size);
779 void PatchWin32Resources (ByteBuffer resources)
781 PatchResourceDirectoryTable (resources);
784 void PatchResourceDirectoryTable (ByteBuffer resources)
786 resources.Advance (12);
788 var entries = resources.ReadUInt16 () + resources.ReadUInt16 ();
790 for (int i = 0; i < entries; i++)
791 PatchResourceDirectoryEntry (resources);
794 void PatchResourceDirectoryEntry (ByteBuffer resources)
796 resources.Advance (4);
797 var child = resources.ReadUInt32 ();
799 var position = resources.position;
800 resources.position = (int) child & 0x7fffffff;
802 if ((child & 0x80000000) != 0)
803 PatchResourceDirectoryTable (resources);
805 PatchResourceDataEntry (resources);
807 resources.position = position;
810 void PatchResourceDataEntry (ByteBuffer resources)
812 var old_rsrc = GetImageResourceSection ();
813 var rva = resources.ReadUInt32 ();
814 resources.position -= 4;
815 resources.WriteUInt32 (rva - old_rsrc.VirtualAddress + rsrc.VirtualAddress);