5 // Jb Evain (jbevain@gmail.com)
7 // Copyright (c) 2008 - 2011 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.pe64 = module.Architecture != TargetArchitecture.I386;
75 this.GetDebugHeader ();
76 this.GetWin32Resources ();
77 this.text_map = BuildTextMap ();
78 this.sections = (ushort) (pe64 ? 1 : 2); // text + reloc
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);
137 reloc = CreateSection (".reloc", 12u, previous);
140 Section CreateSection (string name, uint size, Section previous)
144 VirtualAddress = previous != null
145 ? previous.VirtualAddress + Align (previous.VirtualSize, section_alignment)
148 PointerToRawData = previous != null
149 ? previous.PointerToRawData + previous.SizeOfRawData
150 : Align (GetHeaderSize (), file_alignment),
151 SizeOfRawData = Align (size, file_alignment)
155 static uint Align (uint value, uint align)
158 return (value + align) & ~align;
161 void WriteDOSHeader ()
165 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00,
166 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff,
167 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00,
168 0x00, 0x00, 0x00, 0x40, 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, 0x00, 0x00, 0x00,
173 0x00, 0x00, 0x00, 0x00,
175 0x80, 0x00, 0x00, 0x00,
177 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09,
178 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21,
179 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72,
180 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63,
181 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62,
182 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69,
183 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20, 0x6d,
184 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,
185 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
190 void WritePEFileHeader ()
192 WriteUInt32 (0x00004550); // Magic
193 WriteUInt16 (GetMachine ()); // Machine
194 WriteUInt16 (sections); // NumberOfSections
195 WriteUInt32 (time_stamp);
196 WriteUInt32 (0); // PointerToSymbolTable
197 WriteUInt32 (0); // NumberOfSymbols
198 WriteUInt16 ((ushort) (!pe64 ? 0xe0 : 0xf0)); // SizeOfOptionalHeader
200 // ExecutableImage | (pe64 ? 32BitsMachine : LargeAddressAware)
201 var characteristics = (ushort) (0x0002 | (!pe64 ? 0x0100 : 0x0020));
202 if (module.Kind == ModuleKind.Dll || module.Kind == ModuleKind.NetModule)
203 characteristics |= 0x2000;
204 WriteUInt16 (characteristics); // Characteristics
209 switch (module.Architecture) {
210 case TargetArchitecture.I386:
212 case TargetArchitecture.AMD64:
214 case TargetArchitecture.IA64:
218 throw new NotSupportedException ();
221 Section LastSection ()
232 void WriteOptionalHeaders ()
234 WriteUInt16 ((ushort) (!pe64 ? 0x10b : 0x20b)); // Magic
235 WriteByte (8); // LMajor
236 WriteByte (0); // LMinor
237 WriteUInt32 (text.SizeOfRawData); // CodeSize
238 WriteUInt32 (reloc != null ? reloc.SizeOfRawData : 0
239 + (rsrc != null ? rsrc.SizeOfRawData : 0)); // InitializedDataSize
240 WriteUInt32 (0); // UninitializedDataSize
242 var startub_stub = text_map.GetRange (TextSegment.StartupStub);
243 WriteUInt32 (startub_stub.Length > 0 ? startub_stub.Start : 0); // EntryPointRVA
244 WriteUInt32 (text_rva); // BaseOfCode
247 WriteUInt32 (0); // BaseOfData
248 WriteUInt32 ((uint) image_base); // ImageBase
250 WriteUInt64 (image_base); // ImageBase
253 WriteUInt32 (section_alignment); // SectionAlignment
254 WriteUInt32 (file_alignment); // FileAlignment
256 WriteUInt16 (4); // OSMajor
257 WriteUInt16 (0); // OSMinor
258 WriteUInt16 (0); // UserMajor
259 WriteUInt16 (0); // UserMinor
260 WriteUInt16 (4); // SubSysMajor
261 WriteUInt16 (0); // SubSysMinor
262 WriteUInt32 (0); // Reserved
264 var last_section = LastSection();
265 WriteUInt32 (last_section.VirtualAddress + Align (last_section.VirtualSize, section_alignment)); // ImageSize
266 WriteUInt32 (text.PointerToRawData); // HeaderSize
268 WriteUInt32 (0); // Checksum
269 WriteUInt16 (GetSubSystem ()); // SubSystem
270 WriteUInt16 (0x8540); // DLLFlags
272 const ulong stack_reserve = 0x100000;
273 const ulong stack_commit = 0x1000;
274 const ulong heap_reserve = 0x100000;
275 const ulong heap_commit = 0x1000;
278 WriteUInt32 ((uint) stack_reserve);
279 WriteUInt32 ((uint) stack_commit);
280 WriteUInt32 ((uint) heap_reserve);
281 WriteUInt32 ((uint) heap_commit);
283 WriteUInt64 (stack_reserve);
284 WriteUInt64 (stack_commit);
285 WriteUInt64 (heap_reserve);
286 WriteUInt64 (heap_commit);
289 WriteUInt32 (0); // LoaderFlags
290 WriteUInt32 (16); // NumberOfDataDir
292 WriteZeroDataDirectory (); // ExportTable
293 WriteDataDirectory (text_map.GetDataDirectory (TextSegment.ImportDirectory)); // ImportTable
294 if (rsrc != null) { // ResourceTable
295 WriteUInt32 (rsrc.VirtualAddress);
296 WriteUInt32 (rsrc.VirtualSize);
298 WriteZeroDataDirectory ();
300 WriteZeroDataDirectory (); // ExceptionTable
301 WriteZeroDataDirectory (); // CertificateTable
302 WriteUInt32 (reloc != null ? reloc.VirtualAddress : 0); // BaseRelocationTable
303 WriteUInt32 (reloc != null ? reloc.VirtualSize : 0);
305 if (text_map.GetLength (TextSegment.DebugDirectory) > 0) {
306 WriteUInt32 (text_map.GetRVA (TextSegment.DebugDirectory));
309 WriteZeroDataDirectory ();
311 WriteZeroDataDirectory (); // Copyright
312 WriteZeroDataDirectory (); // GlobalPtr
313 WriteZeroDataDirectory (); // TLSTable
314 WriteZeroDataDirectory (); // LoadConfigTable
315 WriteZeroDataDirectory (); // BoundImport
316 WriteDataDirectory (text_map.GetDataDirectory (TextSegment.ImportAddressTable)); // IAT
317 WriteZeroDataDirectory (); // DelayImportDesc
318 WriteDataDirectory (text_map.GetDataDirectory (TextSegment.CLIHeader)); // CLIHeader
319 WriteZeroDataDirectory (); // Reserved
322 void WriteZeroDataDirectory ()
328 ushort GetSubSystem ()
330 switch (module.Kind) {
331 case ModuleKind.Console:
333 case ModuleKind.NetModule:
335 case ModuleKind.Windows:
338 throw new ArgumentOutOfRangeException ();
342 void WriteSectionHeaders ()
344 WriteSection (text, 0x60000020);
347 WriteSection (rsrc, 0x40000040);
350 WriteSection (reloc, 0x42000040);
353 void WriteSection (Section section, uint characteristics)
355 var name = new byte [8];
356 var sect_name = section.Name;
357 for (int i = 0; i < sect_name.Length; i++)
358 name [i] = (byte) sect_name [i];
361 WriteUInt32 (section.VirtualSize);
362 WriteUInt32 (section.VirtualAddress);
363 WriteUInt32 (section.SizeOfRawData);
364 WriteUInt32 (section.PointerToRawData);
365 WriteUInt32 (0); // PointerToRelocations
366 WriteUInt32 (0); // PointerToLineNumbers
367 WriteUInt16 (0); // NumberOfRelocations
368 WriteUInt16 (0); // NumberOfLineNumbers
369 WriteUInt32 (characteristics);
372 void MoveTo (uint pointer)
374 BaseStream.Seek (pointer, SeekOrigin.Begin);
377 void MoveToRVA (Section section, RVA rva)
379 BaseStream.Seek (section.PointerToRawData + rva - section.VirtualAddress, SeekOrigin.Begin);
382 void MoveToRVA (TextSegment segment)
384 MoveToRVA (text, text_map.GetRVA (segment));
387 void WriteRVA (RVA rva)
397 MoveTo (text.PointerToRawData);
399 // ImportAddressTable
402 WriteRVA (text_map.GetRVA (TextSegment.ImportHintNameTable));
410 WriteUInt16 ((ushort) ((module.Runtime <= TargetRuntime.Net_1_1) ? 0 : 5));
412 WriteUInt32 (text_map.GetRVA (TextSegment.MetadataHeader));
413 WriteUInt32 (GetMetadataLength ());
414 WriteUInt32 ((uint) module.Attributes);
415 WriteUInt32 (metadata.entry_point.ToUInt32 ());
416 WriteDataDirectory (text_map.GetDataDirectory (TextSegment.Resources));
417 WriteDataDirectory (text_map.GetDataDirectory (TextSegment.StrongNameSignature));
418 WriteZeroDataDirectory (); // CodeManagerTable
419 WriteZeroDataDirectory (); // VTableFixups
420 WriteZeroDataDirectory (); // ExportAddressTableJumps
421 WriteZeroDataDirectory (); // ManagedNativeHeader
425 MoveToRVA (TextSegment.Code);
426 WriteBuffer (metadata.code);
430 MoveToRVA (TextSegment.Resources);
431 WriteBuffer (metadata.resources);
435 if (metadata.data.length > 0) {
436 MoveToRVA (TextSegment.Data);
437 WriteBuffer (metadata.data);
440 // StrongNameSignature
445 MoveToRVA (TextSegment.MetadataHeader);
446 WriteMetadataHeader ();
451 if (text_map.GetLength (TextSegment.DebugDirectory) > 0) {
452 MoveToRVA (TextSegment.DebugDirectory);
453 WriteDebugDirectory ();
460 MoveToRVA (TextSegment.ImportDirectory);
461 WriteImportDirectory ();
464 MoveToRVA (TextSegment.StartupStub);
468 uint GetMetadataLength ()
470 return text_map.GetRVA (TextSegment.DebugDirectory) - text_map.GetRVA (TextSegment.MetadataHeader);
473 void WriteMetadataHeader ()
475 WriteUInt32 (0x424a5342); // Signature
476 WriteUInt16 (1); // MajorVersion
477 WriteUInt16 (1); // MinorVersion
478 WriteUInt32 (0); // Reserved
480 var version = GetZeroTerminatedString (GetVersion ());
481 WriteUInt32 ((uint) version.Length);
482 WriteBytes (version);
483 WriteUInt16 (0); // Flags
484 WriteUInt16 (GetStreamCount ());
486 uint offset = text_map.GetRVA (TextSegment.TableHeap) - text_map.GetRVA (TextSegment.MetadataHeader);
488 WriteStreamHeader (ref offset, TextSegment.TableHeap, "#~");
489 WriteStreamHeader (ref offset, TextSegment.StringHeap, "#Strings");
490 WriteStreamHeader (ref offset, TextSegment.UserStringHeap, "#US");
491 WriteStreamHeader (ref offset, TextSegment.GuidHeap, "#GUID");
492 WriteStreamHeader (ref offset, TextSegment.BlobHeap, "#Blob");
497 switch (module.Runtime) {
498 case TargetRuntime.Net_1_0:
500 case TargetRuntime.Net_1_1:
502 case TargetRuntime.Net_2_0:
504 case TargetRuntime.Net_4_0:
510 ushort GetStreamCount ()
515 + (metadata.user_string_heap.IsEmpty ? 0 : 1) // #US
517 + (metadata.blob_heap.IsEmpty ? 0 : 1)); // #Blob
520 void WriteStreamHeader (ref uint offset, TextSegment heap, string name)
522 var length = (uint) text_map.GetLength (heap);
526 WriteUInt32 (offset);
527 WriteUInt32 (length);
528 WriteBytes (GetZeroTerminatedString (name));
532 static byte [] GetZeroTerminatedString (string @string)
534 return GetString (@string, (@string.Length + 1 + 3) & ~3);
537 static byte [] GetSimpleString (string @string)
539 return GetString (@string, @string.Length);
542 static byte [] GetString (string @string, int length)
544 var bytes = new byte [length];
545 for (int i = 0; i < @string.Length; i++)
546 bytes [i] = (byte) @string [i];
551 void WriteMetadata ()
553 WriteHeap (TextSegment.TableHeap, metadata.table_heap);
554 WriteHeap (TextSegment.StringHeap, metadata.string_heap);
555 WriteHeap (TextSegment.UserStringHeap, metadata.user_string_heap);
557 WriteHeap (TextSegment.BlobHeap, metadata.blob_heap);
560 void WriteHeap (TextSegment heap, HeapBuffer buffer)
566 WriteBuffer (buffer);
569 void WriteGuidHeap ()
571 MoveToRVA (TextSegment.GuidHeap);
572 WriteBytes (module.Mvid.ToByteArray ());
575 void WriteDebugDirectory ()
577 WriteInt32 (debug_directory.Characteristics);
578 WriteUInt32 (time_stamp);
579 WriteInt16 (debug_directory.MajorVersion);
580 WriteInt16 (debug_directory.MinorVersion);
581 WriteInt32 (debug_directory.Type);
582 WriteInt32 (debug_directory.SizeOfData);
583 WriteInt32 (debug_directory.AddressOfRawData);
584 WriteInt32 ((int) BaseStream.Position + 4);
586 WriteBytes (debug_data);
589 void WriteImportDirectory ()
591 WriteUInt32 (text_map.GetRVA (TextSegment.ImportDirectory) + 40); // ImportLookupTable
592 WriteUInt32 (0); // DateTimeStamp
593 WriteUInt32 (0); // ForwarderChain
594 WriteUInt32 (text_map.GetRVA (TextSegment.ImportHintNameTable) + 14);
595 WriteUInt32 (text_map.GetRVA (TextSegment.ImportAddressTable));
599 WriteUInt32 (text_map.GetRVA (TextSegment.ImportHintNameTable));
601 // ImportHintNameTable
602 MoveToRVA (TextSegment.ImportHintNameTable);
604 WriteUInt16 (0); // Hint
605 WriteBytes (GetRuntimeMain ());
607 WriteBytes (GetSimpleString ("mscoree.dll"));
611 byte [] GetRuntimeMain ()
613 return module.Kind == ModuleKind.Dll || module.Kind == ModuleKind.NetModule
614 ? GetSimpleString ("_CorDllMain")
615 : GetSimpleString ("_CorExeMain");
618 void WriteStartupStub ()
620 switch (module.Architecture) {
621 case TargetArchitecture.I386:
622 WriteUInt16 (0x25ff);
623 WriteUInt32 ((uint) image_base + text_map.GetRVA (TextSegment.ImportAddressTable));
626 throw new NotSupportedException ();
632 MoveTo (rsrc.PointerToRawData);
633 WriteBuffer (win32_resources);
638 MoveTo (reloc.PointerToRawData);
640 var reloc_rva = text_map.GetRVA (TextSegment.StartupStub);
641 reloc_rva += module.Architecture == TargetArchitecture.IA64 ? 0x20u : 2;
642 var page_rva = reloc_rva & ~0xfffu;
644 WriteUInt32 (page_rva); // PageRVA
645 WriteUInt32 (0x000c); // Block Size
647 switch (module.Architecture) {
648 case TargetArchitecture.I386:
649 WriteUInt32 (0x3000 + reloc_rva - page_rva);
652 throw new NotSupportedException();
655 WriteBytes (new byte [file_alignment - reloc.VirtualSize]);
658 public void WriteImage ()
661 WritePEFileHeader ();
662 WriteOptionalHeaders ();
663 WriteSectionHeaders ();
671 TextMap BuildTextMap ()
673 var map = metadata.text_map;
675 map.AddMap (TextSegment.Code, metadata.code.length, !pe64 ? 4 : 16);
676 map.AddMap (TextSegment.Resources, metadata.resources.length, 8);
677 map.AddMap (TextSegment.Data, metadata.data.length, 4);
678 if (metadata.data.length > 0)
679 metadata.table_heap.FixupData (map.GetRVA (TextSegment.Data));
680 map.AddMap (TextSegment.StrongNameSignature, GetStrongNameLength (), 4);
682 map.AddMap (TextSegment.MetadataHeader, GetMetadataHeaderLength ());
683 map.AddMap (TextSegment.TableHeap, metadata.table_heap.length, 4);
684 map.AddMap (TextSegment.StringHeap, metadata.string_heap.length, 4);
685 map.AddMap (TextSegment.UserStringHeap, metadata.user_string_heap.IsEmpty ? 0 : metadata.user_string_heap.length, 4);
686 map.AddMap (TextSegment.GuidHeap, 16);
687 map.AddMap (TextSegment.BlobHeap, metadata.blob_heap.IsEmpty ? 0 : metadata.blob_heap.length, 4);
689 int debug_dir_len = 0;
690 if (!debug_data.IsNullOrEmpty ()) {
691 const int debug_dir_header_len = 28;
693 debug_directory.AddressOfRawData = (int) map.GetNextRVA (TextSegment.BlobHeap) + debug_dir_header_len;
694 debug_dir_len = debug_data.Length + debug_dir_header_len;
697 map.AddMap (TextSegment.DebugDirectory, debug_dir_len, 4);
700 var start = map.GetNextRVA (TextSegment.DebugDirectory);
701 map.AddMap (TextSegment.ImportDirectory, new Range (start, 0));
702 map.AddMap (TextSegment.ImportHintNameTable, new Range (start, 0));
703 map.AddMap (TextSegment.StartupStub, new Range (start, 0));
707 RVA import_dir_rva = map.GetNextRVA (TextSegment.DebugDirectory);
708 RVA import_hnt_rva = import_dir_rva + 48u;
709 import_hnt_rva = (import_hnt_rva + 15u) & ~15u;
710 uint import_dir_len = (import_hnt_rva - import_dir_rva) + 27u;
712 RVA startup_stub_rva = import_dir_rva + import_dir_len;
713 startup_stub_rva = module.Architecture == TargetArchitecture.IA64
714 ? (startup_stub_rva + 15u) & ~15u
715 : 2 + ((startup_stub_rva + 3u) & ~3u);
717 map.AddMap (TextSegment.ImportDirectory, new Range (import_dir_rva, import_dir_len));
718 map.AddMap (TextSegment.ImportHintNameTable, new Range (import_hnt_rva, 0));
719 map.AddMap (TextSegment.StartupStub, new Range (startup_stub_rva, GetStartupStubLength ()));
724 uint GetStartupStubLength ()
726 switch (module.Architecture) {
727 case TargetArchitecture.I386:
730 throw new NotSupportedException ();
734 int GetMetadataHeaderLength ()
744 + (metadata.user_string_heap.IsEmpty ? 0 : 12)
748 + (metadata.blob_heap.IsEmpty ? 0 : 16);
751 int GetStrongNameLength ()
753 if (module.Assembly == null)
756 var public_key = module.Assembly.Name.PublicKey;
758 if (public_key != null) {
759 // in fx 2.0 the key may be from 384 to 16384 bits
760 // so we must calculate the signature size based on
761 // the size of the public key (minus the 32 byte header)
762 int size = public_key.Length;
765 // note: size == 16 for the ECMA "key" which is replaced
766 // by the runtime with a 1024 bits key (128 bytes)
769 return 128; // default strongname signature size
772 public DataDirectory GetStrongNameSignatureDirectory ()
774 return text_map.GetDataDirectory (TextSegment.StrongNameSignature);
777 public uint GetHeaderSize ()
779 return pe_header_size + (sections * section_header_size);
782 void PatchWin32Resources (ByteBuffer resources)
784 PatchResourceDirectoryTable (resources);
787 void PatchResourceDirectoryTable (ByteBuffer resources)
789 resources.Advance (12);
791 var entries = resources.ReadUInt16 () + resources.ReadUInt16 ();
793 for (int i = 0; i < entries; i++)
794 PatchResourceDirectoryEntry (resources);
797 void PatchResourceDirectoryEntry (ByteBuffer resources)
799 resources.Advance (4);
800 var child = resources.ReadUInt32 ();
802 var position = resources.position;
803 resources.position = (int) child & 0x7fffffff;
805 if ((child & 0x80000000) != 0)
806 PatchResourceDirectoryTable (resources);
808 PatchResourceDataEntry (resources);
810 resources.position = position;
813 void PatchResourceDataEntry (ByteBuffer resources)
815 var old_rsrc = GetImageResourceSection ();
816 var rva = resources.ReadUInt32 ();
817 resources.position -= 4;
818 resources.WriteUInt32 (rva - old_rsrc.VirtualAddress + rsrc.VirtualAddress);