Update mcs/class/Commons.Xml.Relaxng/Commons.Xml.Relaxng/RelaxngPattern.cs
[mono.git] / mcs / class / IKVM.Reflection / Writer / PEWriter.cs
1 /*
2   Copyright (C) 2008 Jeroen Frijters
3
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.
7
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:
11
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.
19
20   Jeroen Frijters
21   jeroen@frijters.net
22   
23 */
24 using System;
25 using System.IO;
26 using BYTE = System.Byte;
27 using WORD = System.UInt16;
28 using DWORD = System.UInt32;
29 using ULONGLONG = System.UInt64;
30 using IMAGE_DATA_DIRECTORY = IKVM.Reflection.Reader.IMAGE_DATA_DIRECTORY;
31
32 namespace IKVM.Reflection.Writer
33 {
34         sealed class PEWriter
35         {
36                 private readonly BinaryWriter bw;
37                 private readonly IMAGE_NT_HEADERS hdr = new IMAGE_NT_HEADERS();
38
39                 internal PEWriter(Stream stream)
40                 {
41                         bw = new BinaryWriter(stream);
42                         WriteMSDOSHeader();
43                 }
44
45                 public IMAGE_NT_HEADERS Headers
46                 {
47                         get { return hdr; }
48                 }
49
50                 public uint HeaderSize
51                 {
52                         get
53                         {
54                                 return (uint)
55                                         ((8 * 16) +     // MSDOS header
56                                         4 +                             // signature
57                                         20 +                    // IMAGE_FILE_HEADER
58                                         hdr.FileHeader.SizeOfOptionalHeader +
59                                         hdr.FileHeader.NumberOfSections * 40);
60                         }
61                 }
62
63                 private void WriteMSDOSHeader()
64                 {
65                         bw.Write(new byte[] {
66                                 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,
67                                 0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
68                                 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00,     0x00, 0x00,
69                                 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73                                 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
74                                 0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD,
75                                 0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68,
76                                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72,
77                                 0x61, 0x6D, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F,
78                                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6E,
79                                 0x20, 0x69, 0x6E, 0x20, 0x44, 0x4F, 0x53, 0x20,
80                                 0x6D, 0x6F, 0x64, 0x65, 0x2E, 0x0D, 0x0D, 0x0A,
81                                 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
82                         });
83                 }
84
85                 internal void WritePEHeaders()
86                 {
87                         bw.Write(hdr.Signature);
88
89                         // IMAGE_FILE_HEADER
90                         bw.Write(hdr.FileHeader.Machine);
91                         bw.Write(hdr.FileHeader.NumberOfSections);
92                         bw.Write(hdr.FileHeader.TimeDateStamp);
93                         bw.Write(hdr.FileHeader.PointerToSymbolTable);
94                         bw.Write(hdr.FileHeader.NumberOfSymbols);
95                         bw.Write(hdr.FileHeader.SizeOfOptionalHeader);
96                         bw.Write(hdr.FileHeader.Characteristics);
97
98                         // IMAGE_OPTIONAL_HEADER
99                         hdr.OptionalHeader.Write(bw);
100                 }
101
102                 internal void WriteSectionHeader(SectionHeader sectionHeader)
103                 {
104                         byte[] name = new byte[8];
105                         System.Text.Encoding.UTF8.GetBytes(sectionHeader.Name, 0, sectionHeader.Name.Length, name, 0);
106                         bw.Write(name);
107                         bw.Write(sectionHeader.VirtualSize);
108                         bw.Write(sectionHeader.VirtualAddress);
109                         bw.Write(sectionHeader.SizeOfRawData);
110                         bw.Write(sectionHeader.PointerToRawData);
111                         bw.Write(sectionHeader.PointerToRelocations);
112                         bw.Write(sectionHeader.PointerToLinenumbers);
113                         bw.Write(sectionHeader.NumberOfRelocations);
114                         bw.Write(sectionHeader.NumberOfLinenumbers);
115                         bw.Write(sectionHeader.Characteristics);
116                 }
117
118                 internal uint ToFileAlignment(uint p)
119                 {
120                         return (p + (Headers.OptionalHeader.FileAlignment - 1)) & ~(Headers.OptionalHeader.FileAlignment - 1);
121                 }
122
123                 internal uint ToSectionAlignment(uint p)
124                 {
125                         return (p + (Headers.OptionalHeader.SectionAlignment - 1)) & ~(Headers.OptionalHeader.SectionAlignment - 1);
126                 }
127         }
128
129         sealed class IMAGE_NT_HEADERS
130         {
131                 public DWORD Signature = 0x00004550;    // "PE\0\0"
132                 public IMAGE_FILE_HEADER FileHeader = new IMAGE_FILE_HEADER();
133                 public IMAGE_OPTIONAL_HEADER OptionalHeader = new IMAGE_OPTIONAL_HEADER();
134         }
135
136         sealed class IMAGE_FILE_HEADER
137         {
138                 public const WORD IMAGE_FILE_MACHINE_I386 = 0x014c;
139                 public const WORD IMAGE_FILE_MACHINE_ARM = 0x01c4;
140                 public const WORD IMAGE_FILE_MACHINE_IA64 = 0x0200;
141                 public const WORD IMAGE_FILE_MACHINE_AMD64 = 0x8664;
142
143                 public const WORD IMAGE_FILE_32BIT_MACHINE = 0x0100;
144                 public const WORD IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002;
145                 public const WORD IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020;
146                 public const WORD IMAGE_FILE_DLL = 0x2000;
147
148                 public WORD Machine;
149                 public WORD NumberOfSections;
150                 public DWORD TimeDateStamp = (uint)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
151                 public DWORD PointerToSymbolTable = 0;
152                 public DWORD NumberOfSymbols = 0;
153                 public WORD SizeOfOptionalHeader = 0xE0;
154                 public WORD Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE;
155         }
156
157         sealed class IMAGE_OPTIONAL_HEADER
158         {
159                 public const WORD IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
160                 public const WORD IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
161
162                 public const WORD IMAGE_SUBSYSTEM_WINDOWS_GUI = 2;
163                 public const WORD IMAGE_SUBSYSTEM_WINDOWS_CUI = 3;
164
165                 public WORD Magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC;
166                 public BYTE MajorLinkerVersion = 8;
167                 public BYTE MinorLinkerVersion = 0;
168                 public DWORD SizeOfCode;
169                 public DWORD SizeOfInitializedData;
170                 public DWORD SizeOfUninitializedData;
171                 public DWORD AddressOfEntryPoint;
172                 public DWORD BaseOfCode;
173                 public DWORD BaseOfData;
174                 public ULONGLONG ImageBase;
175                 public DWORD SectionAlignment = 0x2000;
176                 public DWORD FileAlignment;
177                 public WORD MajorOperatingSystemVersion = 4;
178                 public WORD MinorOperatingSystemVersion = 0;
179                 public WORD MajorImageVersion = 0;
180                 public WORD MinorImageVersion = 0;
181                 public WORD MajorSubsystemVersion = 4;
182                 public WORD MinorSubsystemVersion = 0;
183                 public DWORD Win32VersionValue = 0;
184                 public DWORD SizeOfImage;
185                 public DWORD SizeOfHeaders;
186                 public DWORD CheckSum = 0;
187                 public WORD Subsystem;
188                 public WORD DllCharacteristics;
189                 public ULONGLONG SizeOfStackReserve;
190                 public ULONGLONG SizeOfStackCommit = 0x1000;
191                 public ULONGLONG SizeOfHeapReserve = 0x100000;
192                 public ULONGLONG SizeOfHeapCommit = 0x1000;
193                 public DWORD LoaderFlags = 0;
194                 public DWORD NumberOfRvaAndSizes = 16;
195                 public IMAGE_DATA_DIRECTORY[] DataDirectory = new IMAGE_DATA_DIRECTORY[16];
196
197                 internal void Write(BinaryWriter bw)
198                 {
199                         bw.Write(Magic);
200                         bw.Write(MajorLinkerVersion);
201                         bw.Write(MinorLinkerVersion);
202                         bw.Write(SizeOfCode);
203                         bw.Write(SizeOfInitializedData);
204                         bw.Write(SizeOfUninitializedData);
205                         bw.Write(AddressOfEntryPoint);
206                         bw.Write(BaseOfCode);
207                         if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
208                         {
209                                 bw.Write(BaseOfData);
210                                 bw.Write((DWORD)ImageBase);
211                         }
212                         else
213                         {
214                                 bw.Write(ImageBase);
215                         }
216                         bw.Write(SectionAlignment);
217                         bw.Write(FileAlignment);
218                         bw.Write(MajorOperatingSystemVersion);
219                         bw.Write(MinorOperatingSystemVersion);
220                         bw.Write(MajorImageVersion);
221                         bw.Write(MinorImageVersion);
222                         bw.Write(MajorSubsystemVersion);
223                         bw.Write(MinorSubsystemVersion);
224                         bw.Write(Win32VersionValue);
225                         bw.Write(SizeOfImage);
226                         bw.Write(SizeOfHeaders);
227                         bw.Write(CheckSum);
228                         bw.Write(Subsystem);
229                         bw.Write(DllCharacteristics);
230                         if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
231                         {
232                                 bw.Write((DWORD)SizeOfStackReserve);
233                         }
234                         else
235                         {
236                                 bw.Write(SizeOfStackReserve);
237                         }
238                         if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
239                         {
240                                 bw.Write((DWORD)SizeOfStackCommit);
241                         }
242                         else
243                         {
244                                 bw.Write(SizeOfStackCommit);
245                         }
246                         if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
247                         {
248                                 bw.Write((DWORD)SizeOfHeapReserve);
249                         }
250                         else
251                         {
252                                 bw.Write(SizeOfHeapReserve);
253                         }
254                         if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
255                         {
256                                 bw.Write((DWORD)SizeOfHeapCommit);
257                         }
258                         else
259                         {
260                                 bw.Write(SizeOfHeapCommit);
261                         }
262                         bw.Write(LoaderFlags);
263                         bw.Write(NumberOfRvaAndSizes);
264                         for (int i = 0; i < DataDirectory.Length; i++)
265                         {
266                                 bw.Write(DataDirectory[i].VirtualAddress);
267                                 bw.Write(DataDirectory[i].Size);
268                         }
269                 }
270         }
271
272         class SectionHeader
273         {
274                 public const DWORD IMAGE_SCN_CNT_CODE = 0x00000020;
275                 public const DWORD IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040;
276                 public const DWORD IMAGE_SCN_MEM_DISCARDABLE = 0x02000000;
277                 public const DWORD IMAGE_SCN_MEM_EXECUTE = 0x20000000;
278                 public const DWORD IMAGE_SCN_MEM_READ = 0x40000000;
279                 public const DWORD IMAGE_SCN_MEM_WRITE = 0x80000000;
280
281                 public string Name;             // 8 byte UTF8 encoded 0-padded
282                 public DWORD VirtualSize;
283                 public DWORD VirtualAddress;
284                 public DWORD SizeOfRawData;
285                 public DWORD PointerToRawData;
286 #pragma warning disable 649 // the follow fields are never assigned to
287                 public DWORD PointerToRelocations;
288                 public DWORD PointerToLinenumbers;
289                 public WORD NumberOfRelocations;
290                 public WORD NumberOfLinenumbers;
291 #pragma warning restore 649
292                 public DWORD Characteristics;
293         }
294 }