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