1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5//
6// CEELOAD reads in the PE file format using LoadLibrary
7// ===========================================================================
8#include "ildasmpch.h"
9
10#include "ceeload.h"
11#include <corhdr.h>
12#include <corimage.h>
13#include "util.hpp"
14#include "pedecoder.h"
15
16/*************************************************************************************/
17// Constructor and destructor!
18/*************************************************************************************/
19PELoader::PELoader()
20{
21 m_hFile = NULL;
22 m_hMod = NULL;
23 m_hMapFile = NULL;
24 m_pNT64 = NULL;
25 m_bIsPE32 = FALSE;
26 m_FileSize = m_FileSizeAligned = 0;
27}
28
29PELoader::~PELoader()
30{
31
32 m_hMod = NULL;
33 m_pNT64 = NULL;
34 // If we have an hFile then we opened this file ourselves!
35 // If we do not then this file was loaded by the OS and the OS will
36 // close it for us.
37 if (m_hFile)
38 this->close();
39}
40
41/*************************************************************************************/
42/*************************************************************************************/
43void PELoader::close()
44{
45
46 // _ASSERTE(m_hFile != NULL);
47 if (m_hFile)
48 {
49 if (m_hMod)
50 UnmapViewOfFile((void*)m_hMod);
51 if (m_hMapFile)
52 CloseHandle(m_hMapFile);
53 CloseHandle(m_hFile);
54
55 m_hMod = NULL;
56 m_hMapFile = NULL;
57 m_hFile = NULL;
58 m_FileSize = m_FileSizeAligned = 0;
59 }
60}
61
62
63BOOL PELoader::open(LPCSTR moduleName)
64{
65 HMODULE newhMod = NULL;
66 DWORD dwFileSizeLow;
67
68 _ASSERTE(moduleName);
69 if (!moduleName)
70 return FALSE;
71
72
73 m_hFile = CreateFileA(moduleName, GENERIC_READ, FILE_SHARE_READ,
74 0, OPEN_EXISTING, 0, 0);
75 if (m_hFile == INVALID_HANDLE_VALUE)
76 return FALSE;
77
78 dwFileSizeLow = GetFileSize( m_hFile, NULL);
79 if (dwFileSizeLow == INVALID_FILE_SIZE)
80 return FALSE;
81 m_FileSize = dwFileSizeLow;
82
83 m_hMapFile = WszCreateFileMapping(m_hFile, NULL, PAGE_READONLY, 0, 0, NULL);
84 if (m_hMapFile == NULL)
85 return FALSE;
86
87 newhMod = (HMODULE) MapViewOfFile(m_hMapFile, FILE_MAP_READ, 0, 0, 0);
88 if (newhMod == NULL)
89 return FALSE;
90 return open(newhMod);
91}
92
93BOOL PELoader::open(const WCHAR* moduleName)
94{
95 HMODULE newhMod = NULL;
96 DWORD dwFileSizeLow;
97
98 _ASSERTE(moduleName);
99 if (!moduleName)
100 return FALSE;
101
102 m_hFile = WszCreateFile(moduleName, GENERIC_READ, FILE_SHARE_READ,
103 0, OPEN_EXISTING, 0, 0);
104 if (m_hFile == INVALID_HANDLE_VALUE)
105 return FALSE;
106
107 dwFileSizeLow = GetFileSize( m_hFile, NULL);
108 if (dwFileSizeLow == INVALID_FILE_SIZE)
109 return FALSE;
110 m_FileSize = dwFileSizeLow;
111
112 m_hMapFile = WszCreateFileMapping(m_hFile, NULL, PAGE_READONLY, 0, 0, NULL);
113 if (m_hMapFile == NULL)
114 return FALSE;
115
116 newhMod = (HMODULE) MapViewOfFile(m_hMapFile, FILE_MAP_READ, 0, 0, 0);
117 if (newhMod == NULL)
118 return FALSE;
119 return open(newhMod);
120}
121
122
123/*************************************************************************************/
124BOOL PELoader::open(HMODULE hMod)
125{
126 IMAGE_DOS_HEADER * pdosHeader;
127
128 // get the dos header...
129 m_hMod = hMod;
130 pdosHeader = (IMAGE_DOS_HEADER*) hMod;
131 // If this is not a PE32+ image
132 if (pdosHeader->e_magic == VAL16(IMAGE_DOS_SIGNATURE) &&
133 0 < VAL32(pdosHeader->e_lfanew) && VAL32(pdosHeader->e_lfanew) < 0xFF0) // has to start on first page
134 {
135 size_t fileAlignment;
136
137 m_pNT32 = (IMAGE_NT_HEADERS32*) ((BYTE *)m_hMod + VAL32(pdosHeader->e_lfanew));
138
139 m_bIsPE32 = (m_pNT32->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR32_MAGIC));
140
141 if (m_bIsPE32)
142 {
143 if ((m_pNT32->Signature != VAL32(IMAGE_NT_SIGNATURE)) ||
144 (m_pNT32->FileHeader.SizeOfOptionalHeader != VAL16(sizeof(IMAGE_OPTIONAL_HEADER32))))
145 {
146 // Make this appear uninitialized because for some reason this file is toasted.
147 m_pNT32 = NULL;
148 m_hMod = NULL;
149 return FALSE;
150 }
151 fileAlignment = VAL32(m_pNT32->OptionalHeader.FileAlignment)-1;
152 }
153 else //For now assume not i386 is IA64
154 {
155 if ((m_pNT64->Signature != VAL32(IMAGE_NT_SIGNATURE)) ||
156 (m_pNT64->FileHeader.SizeOfOptionalHeader != VAL16(sizeof(IMAGE_OPTIONAL_HEADER64))))
157 {
158 // Make this appear uninitialized because for some reason this file is toasted.
159 m_pNT64 = NULL;
160 m_hMod = NULL;
161 return FALSE;
162 }
163 fileAlignment = VAL32(m_pNT64->OptionalHeader.FileAlignment)-1;
164 }
165 m_FileSizeAligned = (m_FileSize + fileAlignment)&(~fileAlignment);
166 }
167 else
168 {
169 // Make this appear uninitialized because for some reason this file is toasted.
170 m_hMod = NULL;
171 return FALSE;
172 }
173 return TRUE;
174}
175
176/*************************************************************************************/
177void PELoader::dump()
178{
179}
180
181/*************************************************************************************/
182BOOL PELoader::getCOMHeader(IMAGE_COR20_HEADER **ppCorHeader)
183{
184 PIMAGE_SECTION_HEADER pSectionHeader;
185
186 if (m_bIsPE32)
187 {
188 PIMAGE_NT_HEADERS32 pImageHeader;
189 // Get the image header from the image, then get the directory location
190 // of the COM+ header which may or may not be filled out.
191 pImageHeader = (PIMAGE_NT_HEADERS32)Cor_RtlImageNtHeader(m_hMod, (ULONG) m_FileSize);
192 PREFIX_ASSUME(pImageHeader != NULL);
193 pSectionHeader = (PIMAGE_SECTION_HEADER) Cor_RtlImageRvaToVa32(pImageHeader, (PBYTE)m_hMod,
194 VAL32(pImageHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COMHEADER].VirtualAddress),
195 (DWORD)m_FileSizeAligned /* FileLength */);
196 }
197 else
198 {
199 PIMAGE_NT_HEADERS64 pImageHeader;
200
201 // Get the image header from the image, then get the directory location
202 // of the COM+ header which may or may not be filled out.
203 pImageHeader = (PIMAGE_NT_HEADERS64)Cor_RtlImageNtHeader(m_hMod, (ULONG) m_FileSize);
204 PREFIX_ASSUME(pImageHeader != NULL);
205 pSectionHeader = (PIMAGE_SECTION_HEADER) Cor_RtlImageRvaToVa64(pImageHeader, (PBYTE)m_hMod,
206 VAL32(pImageHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COMHEADER].VirtualAddress),
207 (DWORD)m_FileSizeAligned /* FileLength */);
208 }
209
210 // If the section header exists, then return ok and the address.
211 if (pSectionHeader)
212 {
213 *ppCorHeader = (IMAGE_COR20_HEADER *) pSectionHeader;
214 return TRUE;
215 }
216 // If there is no COM+ Data in this image, return false.
217 else
218 return FALSE;
219}
220
221/*************************************************************************************/
222BOOL PELoader::getVAforRVA(DWORD rva,void **ppva)
223{
224 PIMAGE_SECTION_HEADER pSectionHeader;
225
226 if (m_bIsPE32)
227 {
228 // Get the image header from the image, then get the directory location
229 // of the COM+ header which may or may not be filled out.
230 PIMAGE_NT_HEADERS32 pImageHeader;
231 pImageHeader = (PIMAGE_NT_HEADERS32) Cor_RtlImageNtHeader(m_hMod, (ULONG) m_FileSize);
232 PREFIX_ASSUME(pImageHeader != NULL);
233 pSectionHeader = (PIMAGE_SECTION_HEADER) Cor_RtlImageRvaToVa32(pImageHeader, (PBYTE)m_hMod,
234 rva, (DWORD)m_FileSizeAligned /* FileLength */);
235 }
236 else
237 {
238 PIMAGE_NT_HEADERS64 pImageHeader;
239 pImageHeader = (PIMAGE_NT_HEADERS64) Cor_RtlImageNtHeader(m_hMod, (ULONG) m_FileSize);
240 PREFIX_ASSUME(pImageHeader != NULL);
241 pSectionHeader = (PIMAGE_SECTION_HEADER) Cor_RtlImageRvaToVa64(pImageHeader, (PBYTE)m_hMod,
242 rva, (DWORD)m_FileSizeAligned /* FileLength */);
243 }
244
245 // If the section header exists, then return ok and the address.
246 if (pSectionHeader)
247 {
248 *ppva = pSectionHeader;
249 return TRUE;
250 }
251 // If there is no COM+ Data in this image, return false.
252 else
253 return FALSE;
254}
255
256void SectionInfo::Init(PELoader *pPELoader, IMAGE_DATA_DIRECTORY *dir)
257{
258 _ASSERTE(dir);
259 m_dwSectionOffset = VAL32(dir->VirtualAddress);
260 if (m_dwSectionOffset != 0)
261 m_pSection = pPELoader->base() + m_dwSectionOffset;
262 else
263 m_pSection = 0;
264 m_dwSectionSize = VAL32(dir->Size);
265}
266
267