2 Copyright (C) 2008-2011 Jeroen Frijters
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
25 using System.Diagnostics;
27 using System.Collections.Generic;
29 using IKVM.Reflection.Emit;
30 using IKVM.Reflection.Impl;
31 using IKVM.Reflection.Metadata;
33 namespace IKVM.Reflection.Writer
35 sealed class TextSection
37 private readonly PEWriter peWriter;
38 private readonly CliHeader cliHeader;
39 private readonly ModuleBuilder moduleBuilder;
40 private readonly uint strongNameSignatureLength;
41 private readonly ExportTables exportTables;
43 internal TextSection(PEWriter peWriter, CliHeader cliHeader, ModuleBuilder moduleBuilder, int strongNameSignatureLength)
45 this.peWriter = peWriter;
46 this.cliHeader = cliHeader;
47 this.moduleBuilder = moduleBuilder;
48 this.strongNameSignatureLength = (uint)strongNameSignatureLength;
49 if (moduleBuilder.unmanagedExports.Count != 0)
51 this.exportTables = new ExportTables(this);
55 internal uint PointerToRawData
57 get { return peWriter.ToFileAlignment(peWriter.HeaderSize); }
62 get { return 0x2000; }
65 internal uint ImportAddressTableRVA
67 get { return BaseRVA; }
70 internal uint ImportAddressTableLength
74 switch (peWriter.Headers.FileHeader.Machine)
76 case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386:
78 case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_ARM:
86 internal uint ComDescriptorRVA
88 get { return ImportAddressTableRVA + ImportAddressTableLength; }
91 internal uint ComDescriptorLength
93 get { return cliHeader.Cb; }
96 internal uint MethodBodiesRVA
98 get { return (ComDescriptorRVA + ComDescriptorLength + 7) & ~7U; }
101 private uint MethodBodiesLength
103 get { return (uint)moduleBuilder.methodBodies.Length; }
106 private uint ResourcesRVA
110 switch (peWriter.Headers.FileHeader.Machine)
112 case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386:
113 case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_ARM:
114 return (MethodBodiesRVA + MethodBodiesLength + 3) & ~3U;
116 return (MethodBodiesRVA + MethodBodiesLength + 15) & ~15U;
121 private uint ResourcesLength
123 get { return (uint)moduleBuilder.manifestResources.Length; }
126 internal uint StrongNameSignatureRVA
130 return (ResourcesRVA + ResourcesLength + 3) & ~3U;
134 internal uint StrongNameSignatureLength
138 return strongNameSignatureLength;
142 private uint MetadataRVA
146 return (StrongNameSignatureRVA + StrongNameSignatureLength + 3) & ~3U;
150 private uint MetadataLength
152 get { return (uint)moduleBuilder.MetadataLength; }
155 private uint VTableFixupsRVA
157 get { return (MetadataRVA + MetadataLength + 7) & ~7U; }
160 private uint VTableFixupsLength
162 get { return (uint)moduleBuilder.vtablefixups.Count * 8; }
165 internal uint DebugDirectoryRVA
167 get { return VTableFixupsRVA + VTableFixupsLength; }
170 internal uint DebugDirectoryLength
174 if (DebugDirectoryContentsLength != 0)
182 private uint DebugDirectoryContentsLength
186 if (moduleBuilder.symbolWriter != null)
188 IMAGE_DEBUG_DIRECTORY idd = new IMAGE_DEBUG_DIRECTORY();
189 return (uint)SymbolSupport.GetDebugInfo(moduleBuilder.symbolWriter, ref idd).Length;
195 internal uint ExportDirectoryRVA
197 get { return (DebugDirectoryRVA + DebugDirectoryLength + DebugDirectoryContentsLength + 15) & ~15U; }
200 internal uint ExportDirectoryLength
202 get { return moduleBuilder.unmanagedExports.Count == 0 ? 0U : 40U; }
205 private uint ExportTablesRVA
207 get { return ExportDirectoryRVA + ExportDirectoryLength; }
210 private uint ExportTablesLength
212 get { return exportTables == null ? 0U : exportTables.Length; }
215 internal uint ImportDirectoryRVA
217 // on AMD64 (and probably IA64) the import directory needs to be 16 byte aligned (on I386 4 byte alignment is sufficient)
218 get { return (ExportTablesRVA + ExportTablesLength + 15) & ~15U; }
221 internal uint ImportDirectoryLength
225 switch (peWriter.Headers.FileHeader.Machine)
227 case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_ARM:
230 return (ImportHintNameTableRVA - ImportDirectoryRVA) + 27;
235 private uint ImportHintNameTableRVA
239 if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386)
241 return (ImportDirectoryRVA + 48 + 15) & ~15U;
245 return (ImportDirectoryRVA + 48 + 4 + 15) & ~15U;
250 internal uint StartupStubRVA
254 if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64)
256 // note that the alignment is driven by the requirement that the two relocation fixups are in a single page
257 return (ImportDirectoryRVA + ImportDirectoryLength + 15U) & ~15U;
261 // the additional 2 bytes padding are to align the address in the jump (which is a relocation fixup)
262 return 2 + ((ImportDirectoryRVA + ImportDirectoryLength + 3U) & ~3U);
267 internal uint StartupStubLength
271 switch (peWriter.Headers.FileHeader.Machine)
273 case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386:
275 case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64:
277 case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64:
285 private void WriteRVA(MetadataWriter mw, uint rva)
287 switch (peWriter.Headers.FileHeader.Machine)
289 case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386:
290 case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_ARM:
294 mw.Write((ulong)rva);
299 internal void Write(MetadataWriter mw, uint sdataRVA)
301 // Now that we're ready to start writing, we need to do some fix ups
302 moduleBuilder.TypeRef.Fixup(moduleBuilder);
303 moduleBuilder.MethodDef.Fixup(this);
304 moduleBuilder.MethodImpl.Fixup(moduleBuilder);
305 moduleBuilder.MethodSemantics.Fixup(moduleBuilder);
306 moduleBuilder.InterfaceImpl.Fixup();
307 moduleBuilder.ResolveInterfaceImplPseudoTokens();
308 moduleBuilder.MemberRef.Fixup(moduleBuilder);
309 moduleBuilder.Constant.Fixup(moduleBuilder);
310 moduleBuilder.FieldMarshal.Fixup(moduleBuilder);
311 moduleBuilder.DeclSecurity.Fixup(moduleBuilder);
312 moduleBuilder.GenericParam.Fixup(moduleBuilder);
313 moduleBuilder.CustomAttribute.Fixup(moduleBuilder);
314 moduleBuilder.FieldLayout.Fixup(moduleBuilder);
315 moduleBuilder.FieldRVA.Fixup(moduleBuilder, (int)sdataRVA, (int)this.MethodBodiesRVA);
316 moduleBuilder.ImplMap.Fixup(moduleBuilder);
317 moduleBuilder.ExportedType.Fixup(moduleBuilder);
318 moduleBuilder.ManifestResource.Fixup(moduleBuilder);
319 moduleBuilder.MethodSpec.Fixup(moduleBuilder);
320 moduleBuilder.GenericParamConstraint.Fixup(moduleBuilder);
322 // Import Address Table
323 AssertRVA(mw, ImportAddressTableRVA);
324 if (ImportAddressTableLength != 0)
326 WriteRVA(mw, ImportHintNameTableRVA);
331 AssertRVA(mw, ComDescriptorRVA);
332 cliHeader.MetaData.VirtualAddress = MetadataRVA;
333 cliHeader.MetaData.Size = MetadataLength;
334 if (ResourcesLength != 0)
336 cliHeader.Resources.VirtualAddress = ResourcesRVA;
337 cliHeader.Resources.Size = ResourcesLength;
339 if (StrongNameSignatureLength != 0)
341 cliHeader.StrongNameSignature.VirtualAddress = StrongNameSignatureRVA;
342 cliHeader.StrongNameSignature.Size = StrongNameSignatureLength;
344 if (VTableFixupsLength != 0)
346 cliHeader.VTableFixups.VirtualAddress = VTableFixupsRVA;
347 cliHeader.VTableFixups.Size = VTableFixupsLength;
352 for (int i = (int)(MethodBodiesRVA - (ComDescriptorRVA + ComDescriptorLength)); i > 0; i--)
358 mw.Write(moduleBuilder.methodBodies);
361 for (int i = (int)(ResourcesRVA - (MethodBodiesRVA + MethodBodiesLength)); i > 0; i--)
367 mw.Write(moduleBuilder.manifestResources);
369 // The strong name signature live here (if it exists), but it will written later
370 // and the following alignment padding will take care of reserving the space.
373 for (int i = (int)(MetadataRVA - (ResourcesRVA + ResourcesLength)); i > 0; i--)
379 AssertRVA(mw, MetadataRVA);
380 moduleBuilder.WriteMetadata(mw);
383 for (int i = (int)(VTableFixupsRVA - (MetadataRVA + MetadataLength)); i > 0; i--)
389 AssertRVA(mw, VTableFixupsRVA);
390 WriteVTableFixups(mw, sdataRVA);
393 AssertRVA(mw, DebugDirectoryRVA);
394 WriteDebugDirectory(mw);
397 for (int i = (int)(ExportDirectoryRVA - (DebugDirectoryRVA + DebugDirectoryLength + DebugDirectoryContentsLength)); i > 0; i--)
403 AssertRVA(mw, ExportDirectoryRVA);
404 WriteExportDirectory(mw);
407 AssertRVA(mw, ExportTablesRVA);
408 WriteExportTables(mw, sdataRVA);
411 for (int i = (int)(ImportDirectoryRVA - (ExportTablesRVA + ExportTablesLength)); i > 0; i--)
417 AssertRVA(mw, ImportDirectoryRVA);
418 if (ImportDirectoryLength != 0)
420 WriteImportDirectory(mw);
424 for (int i = (int)(StartupStubRVA - (ImportDirectoryRVA + ImportDirectoryLength)); i > 0; i--)
430 AssertRVA(mw, StartupStubRVA);
431 if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64)
434 * 48 A1 00 20 40 00 00 00 00 00 mov rax,qword ptr [0000000000402000h]
437 mw.Write((ushort)0xA148);
438 mw.Write(peWriter.Headers.OptionalHeader.ImageBase + ImportAddressTableRVA);
439 mw.Write((ushort)0xE0FF);
441 else if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64)
443 mw.Write(new byte[] {
444 0x0B, 0x48, 0x00, 0x02, 0x18, 0x10, 0xA0, 0x40, 0x24, 0x30, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00,
445 0x10, 0x08, 0x00, 0x12, 0x18, 0x10, 0x60, 0x50, 0x04, 0x80, 0x03, 0x00, 0x60, 0x00, 0x80, 0x00
447 mw.Write(peWriter.Headers.OptionalHeader.ImageBase + StartupStubRVA);
448 mw.Write(peWriter.Headers.OptionalHeader.ImageBase + BaseRVA);
450 else if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386)
452 mw.Write((ushort)0x25FF);
453 mw.Write((uint)peWriter.Headers.OptionalHeader.ImageBase + ImportAddressTableRVA);
457 [Conditional("DEBUG")]
458 private void AssertRVA(MetadataWriter mw, uint rva)
460 Debug.Assert(mw.Position - PointerToRawData + BaseRVA == rva);
463 private void WriteVTableFixups(MetadataWriter mw, uint sdataRVA)
465 foreach (ModuleBuilder.VTableFixups fixups in moduleBuilder.vtablefixups)
467 mw.Write(fixups.initializedDataOffset + sdataRVA);
468 mw.Write(fixups.count);
469 mw.Write(fixups.type);
473 private void WriteDebugDirectory(MetadataWriter mw)
475 if (DebugDirectoryLength != 0)
477 IMAGE_DEBUG_DIRECTORY idd = new IMAGE_DEBUG_DIRECTORY();
478 idd.Characteristics = 0;
479 idd.TimeDateStamp = peWriter.Headers.FileHeader.TimeDateStamp;
480 byte[] buf = SymbolSupport.GetDebugInfo(moduleBuilder.symbolWriter, ref idd);
481 idd.PointerToRawData = (DebugDirectoryRVA - BaseRVA) + DebugDirectoryLength + PointerToRawData;
482 idd.AddressOfRawData = DebugDirectoryRVA + DebugDirectoryLength;
483 mw.Write(idd.Characteristics);
484 mw.Write(idd.TimeDateStamp);
485 mw.Write(idd.MajorVersion);
486 mw.Write(idd.MinorVersion);
488 mw.Write(idd.SizeOfData);
489 mw.Write(idd.AddressOfRawData);
490 mw.Write(idd.PointerToRawData);
495 private sealed class ExportTables
497 private readonly TextSection text;
498 internal readonly uint entries;
499 internal readonly uint ordinalBase;
500 internal readonly uint nameCount;
501 internal readonly uint namesLength;
502 internal readonly uint exportAddressTableRVA;
503 internal readonly uint exportNamePointerTableRVA;
504 internal readonly uint exportOrdinalTableRVA;
505 internal readonly uint namesRVA;
506 internal readonly uint stubsRVA;
507 private readonly uint stubLength;
509 internal ExportTables(TextSection text)
512 ordinalBase = GetOrdinalBase(out entries);
513 namesLength = GetExportNamesLength(out nameCount);
514 exportAddressTableRVA = text.ExportTablesRVA;
515 exportNamePointerTableRVA = exportAddressTableRVA + 4 * entries;
516 exportOrdinalTableRVA = exportNamePointerTableRVA + 4 * nameCount;
517 namesRVA = exportOrdinalTableRVA + 2 * nameCount;
518 stubsRVA = (namesRVA + namesLength + 15) & ~15U;
519 // note that we align the stubs to avoid having to deal with the relocation crossing a page boundary
520 switch (text.peWriter.Headers.FileHeader.Machine)
522 case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386:
525 case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64:
529 throw new NotImplementedException();
535 get { return (stubsRVA + stubLength * (uint)text.moduleBuilder.unmanagedExports.Count) - text.ExportTablesRVA; }
538 private uint GetOrdinalBase(out uint entries)
540 uint min = uint.MaxValue;
541 uint max = uint.MinValue;
542 foreach (UnmanagedExport exp in text.moduleBuilder.unmanagedExports)
544 uint ordinal = (uint)exp.ordinal;
545 min = Math.Min(min, ordinal);
546 max = Math.Max(max, ordinal);
548 entries = 1 + (max - min);
552 private uint GetExportNamesLength(out uint nameCount)
555 // the first name in the names list is the module name (the Export Directory contains a name of the current module)
556 uint length = (uint)text.moduleBuilder.fileName.Length + 1;
557 foreach (UnmanagedExport exp in text.moduleBuilder.unmanagedExports)
559 if (exp.name != null)
562 length += (uint)exp.name.Length + 1;
568 internal void Write(MetadataWriter mw, uint sdataRVA)
570 // sort the exports by ordinal
571 text.moduleBuilder.unmanagedExports.Sort(CompareUnmanagedExportOrdinals);
573 // Now write the Export Address Table
574 text.AssertRVA(mw, exportAddressTableRVA);
575 for (int i = 0, pos = 0; i < entries; i++)
577 if (text.moduleBuilder.unmanagedExports[pos].ordinal == i + ordinalBase)
579 mw.Write(stubsRVA + (uint)pos * stubLength);
588 // sort the exports by name
589 text.moduleBuilder.unmanagedExports.Sort(CompareUnmanagedExportNames);
591 // Now write the Export Name Pointer Table
592 text.AssertRVA(mw, exportNamePointerTableRVA);
593 uint nameOffset = (uint)text.moduleBuilder.fileName.Length + 1;
594 foreach (UnmanagedExport exp in text.moduleBuilder.unmanagedExports)
596 if (exp.name != null)
598 mw.Write(namesRVA + nameOffset);
599 nameOffset += (uint)exp.name.Length + 1;
603 // Now write the Export Ordinal Table
604 text.AssertRVA(mw, exportOrdinalTableRVA);
605 foreach (UnmanagedExport exp in text.moduleBuilder.unmanagedExports)
607 if (exp.name != null)
609 mw.Write((ushort)(exp.ordinal - ordinalBase));
613 // Now write the actual names
614 text.AssertRVA(mw, namesRVA);
615 mw.Write(Encoding.ASCII.GetBytes(text.moduleBuilder.fileName));
617 foreach (UnmanagedExport exp in text.moduleBuilder.unmanagedExports)
619 if (exp.name != null)
621 mw.Write(Encoding.ASCII.GetBytes(exp.name));
625 text.AssertRVA(mw, namesRVA + namesLength);
628 for (int i = (int)(stubsRVA - (namesRVA + namesLength)); i > 0; i--)
633 // sort the exports by ordinal
634 text.moduleBuilder.unmanagedExports.Sort(CompareUnmanagedExportOrdinals);
636 // Now write the stubs
637 text.AssertRVA(mw, stubsRVA);
639 for (int i = 0, pos = 0; i < entries; i++)
641 if (text.moduleBuilder.unmanagedExports[pos].ordinal == i + ordinalBase)
643 switch (text.peWriter.Headers.FileHeader.Machine)
645 case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386:
646 mw.Write((byte)0xFF);
647 mw.Write((byte)0x25);
648 mw.Write((uint)text.peWriter.Headers.OptionalHeader.ImageBase + text.moduleBuilder.unmanagedExports[pos].rva.initializedDataOffset + sdataRVA);
649 mw.Write((short)0); // alignment
651 case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64:
652 mw.Write((byte)0x48);
653 mw.Write((byte)0xA1);
654 mw.Write(text.peWriter.Headers.OptionalHeader.ImageBase + text.moduleBuilder.unmanagedExports[pos].rva.initializedDataOffset + sdataRVA);
655 mw.Write((byte)0xFF);
656 mw.Write((byte)0xE0);
657 mw.Write(0); // alignment
660 throw new NotImplementedException();
667 private static int CompareUnmanagedExportNames(UnmanagedExport x, UnmanagedExport y)
671 return y.name == null ? 0 : 1;
677 return x.name.CompareTo(y.name);
680 private static int CompareUnmanagedExportOrdinals(UnmanagedExport x, UnmanagedExport y)
682 return x.ordinal.CompareTo(y.ordinal);
685 internal void WriteRelocations(MetadataWriter mw)
687 // we assume that unmanagedExports is still sorted by ordinal
688 for (int i = 0, pos = 0; i < entries; i++)
690 if (text.moduleBuilder.unmanagedExports[pos].ordinal == i + ordinalBase)
692 // both I386 and AMD64 have the address at offset 2
693 text.WriteRelocationBlock(mw, stubsRVA + 2 + (uint)pos * stubLength);
700 private uint GetOrdinalBase(out uint entries)
702 uint min = uint.MaxValue;
703 uint max = uint.MinValue;
704 foreach (UnmanagedExport exp in moduleBuilder.unmanagedExports)
706 uint ordinal = (uint)exp.ordinal;
707 min = Math.Min(min, ordinal);
708 max = Math.Max(max, ordinal);
710 entries = 1 + (max - min);
714 private uint GetExportNamesLength(out uint nameCount)
718 foreach (UnmanagedExport exp in moduleBuilder.unmanagedExports)
720 if (exp.name != null)
723 length += (uint)exp.name.Length + 1;
729 private void WriteExportDirectory(MetadataWriter mw)
731 if (ExportDirectoryLength != 0)
736 mw.Write(peWriter.Headers.FileHeader.TimeDateStamp);
742 mw.Write(exportTables.namesRVA);
744 mw.Write(exportTables.ordinalBase);
745 // Address Table Entries
746 mw.Write(exportTables.entries);
747 // Number of Name Pointers
748 mw.Write(exportTables.nameCount);
749 // Export Address Table RVA
750 mw.Write(exportTables.exportAddressTableRVA);
752 mw.Write(exportTables.exportNamePointerTableRVA);
754 mw.Write(exportTables.exportOrdinalTableRVA);
758 private void WriteExportTables(MetadataWriter mw, uint sdataRVA)
760 if (exportTables != null)
762 exportTables.Write(mw, sdataRVA);
766 private void WriteImportDirectory(MetadataWriter mw)
768 mw.Write(ImportDirectoryRVA + 40); // ImportLookupTable
769 mw.Write(0); // DateTimeStamp
770 mw.Write(0); // ForwarderChain
771 mw.Write(ImportHintNameTableRVA + 14); // Name
772 mw.Write(ImportAddressTableRVA);
773 mw.Write(new byte[20]);
774 // Import Lookup Table
775 mw.Write(ImportHintNameTableRVA); // Hint/Name Table RVA
777 if (peWriter.Headers.FileHeader.Machine != IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386)
785 for (int i = (int)(ImportHintNameTableRVA - (ImportDirectoryRVA + size)); i > 0; i--)
791 AssertRVA(mw, ImportHintNameTableRVA);
792 mw.Write((ushort)0); // Hint
793 if ((peWriter.Headers.FileHeader.Characteristics & IMAGE_FILE_HEADER.IMAGE_FILE_DLL) != 0)
795 mw.Write(System.Text.Encoding.ASCII.GetBytes("_CorDllMain"));
799 mw.Write(System.Text.Encoding.ASCII.GetBytes("_CorExeMain"));
803 mw.Write(System.Text.Encoding.ASCII.GetBytes("mscoree.dll"));
809 get { return (int)(StartupStubRVA - BaseRVA + StartupStubLength); }
812 internal void WriteRelocations(MetadataWriter mw)
814 uint relocAddress = this.StartupStubRVA;
815 switch (peWriter.Headers.FileHeader.Machine)
817 case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386:
818 case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64:
821 case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64:
822 relocAddress += 0x20;
825 WriteRelocationBlock(mw, relocAddress);
826 if (exportTables != null)
828 exportTables.WriteRelocations(mw);
832 // note that we're lazy and write a new relocation block for every relocation
833 // even if they are in the same page (since there is typically only one anyway)
834 private void WriteRelocationBlock(MetadataWriter mw, uint relocAddress)
836 uint pageRVA = relocAddress & ~0xFFFU;
837 mw.Write(pageRVA); // PageRVA
838 mw.Write(0x000C); // Block Size
839 switch (peWriter.Headers.FileHeader.Machine)
841 case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386:
842 mw.Write(0x3000 + relocAddress - pageRVA); // Type / Offset
844 case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64:
845 mw.Write(0xA000 + relocAddress - pageRVA); // Type / Offset
847 case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64:
848 // on IA64 the StartupStubRVA is 16 byte aligned, so these two addresses won't cross a page boundary
849 mw.Write((short)(0xA000 + relocAddress - pageRVA)); // Type / Offset
850 mw.Write((short)(0xA000 + relocAddress - pageRVA + 8)); // Type / Offset