OLD | NEW |
| (Empty) |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // This file implements PEImage, a generic class to manipulate PE files. | |
6 // This file was adapted from GreenBorder's Code. | |
7 | |
8 #include "base/pe_image.h" | |
9 | |
10 #if defined(_WIN64) && !defined(NACL_WIN64) | |
11 // TODO(rvargas): Bug 27218. Make sure this is ok. | |
12 #error This code is not tested on x64. Please make sure all the base unit tests\ | |
13 pass before doing any real work. The current unit tests don't test the\ | |
14 differences between 32- and 64-bits implementations. Bugs may slip through.\ | |
15 You need to improve the coverage before continuing. | |
16 #endif | |
17 | |
18 // Structure to perform imports enumerations. | |
19 struct EnumAllImportsStorage { | |
20 PEImage::EnumImportsFunction callback; | |
21 PVOID cookie; | |
22 }; | |
23 | |
24 namespace { | |
25 | |
26 // Compare two strings byte by byte on an unsigned basis. | |
27 // if s1 == s2, return 0 | |
28 // if s1 < s2, return negative | |
29 // if s1 > s2, return positive | |
30 // Exception if inputs are invalid. | |
31 int StrCmpByByte(LPCSTR s1, LPCSTR s2) { | |
32 while (*s1 != '\0' && *s1 == *s2) { | |
33 ++s1; | |
34 ++s2; | |
35 } | |
36 | |
37 return (*reinterpret_cast<const unsigned char*>(s1) - | |
38 *reinterpret_cast<const unsigned char*>(s2)); | |
39 } | |
40 | |
41 } // namespace | |
42 | |
43 // Callback used to enumerate imports. See EnumImportChunksFunction. | |
44 bool ProcessImportChunk(const PEImage &image, LPCSTR module, | |
45 PIMAGE_THUNK_DATA name_table, | |
46 PIMAGE_THUNK_DATA iat, PVOID cookie) { | |
47 EnumAllImportsStorage &storage = *reinterpret_cast<EnumAllImportsStorage*>( | |
48 cookie); | |
49 | |
50 return image.EnumOneImportChunk(storage.callback, module, name_table, iat, | |
51 storage.cookie); | |
52 } | |
53 | |
54 // Callback used to enumerate delay imports. See EnumDelayImportChunksFunction. | |
55 bool ProcessDelayImportChunk(const PEImage &image, | |
56 PImgDelayDescr delay_descriptor, | |
57 LPCSTR module, PIMAGE_THUNK_DATA name_table, | |
58 PIMAGE_THUNK_DATA iat, PIMAGE_THUNK_DATA bound_iat, | |
59 PIMAGE_THUNK_DATA unload_iat, PVOID cookie) { | |
60 EnumAllImportsStorage &storage = *reinterpret_cast<EnumAllImportsStorage*>( | |
61 cookie); | |
62 | |
63 return image.EnumOneDelayImportChunk(storage.callback, delay_descriptor, | |
64 module, name_table, iat, bound_iat, | |
65 unload_iat, storage.cookie); | |
66 } | |
67 | |
68 void PEImage::set_module(HMODULE module) { | |
69 module_ = module; | |
70 } | |
71 | |
72 PIMAGE_DOS_HEADER PEImage::GetDosHeader() const { | |
73 return reinterpret_cast<PIMAGE_DOS_HEADER>(module_); | |
74 } | |
75 | |
76 PIMAGE_NT_HEADERS PEImage::GetNTHeaders() const { | |
77 PIMAGE_DOS_HEADER dos_header = GetDosHeader(); | |
78 | |
79 return reinterpret_cast<PIMAGE_NT_HEADERS>( | |
80 reinterpret_cast<char*>(dos_header) + dos_header->e_lfanew); | |
81 } | |
82 | |
83 PIMAGE_SECTION_HEADER PEImage::GetSectionHeader(UINT section) const { | |
84 PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); | |
85 PIMAGE_SECTION_HEADER first_section = IMAGE_FIRST_SECTION(nt_headers); | |
86 | |
87 if (section < nt_headers->FileHeader.NumberOfSections) | |
88 return first_section + section; | |
89 else | |
90 return NULL; | |
91 } | |
92 | |
93 WORD PEImage::GetNumSections() const { | |
94 return GetNTHeaders()->FileHeader.NumberOfSections; | |
95 } | |
96 | |
97 DWORD PEImage::GetImageDirectoryEntrySize(UINT directory) const { | |
98 PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); | |
99 | |
100 return nt_headers->OptionalHeader.DataDirectory[directory].Size; | |
101 } | |
102 | |
103 PVOID PEImage::GetImageDirectoryEntryAddr(UINT directory) const { | |
104 PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); | |
105 | |
106 return RVAToAddr( | |
107 nt_headers->OptionalHeader.DataDirectory[directory].VirtualAddress); | |
108 } | |
109 | |
110 PIMAGE_SECTION_HEADER PEImage::GetImageSectionFromAddr(PVOID address) const { | |
111 PBYTE target = reinterpret_cast<PBYTE>(address); | |
112 PIMAGE_SECTION_HEADER section; | |
113 | |
114 for (UINT i = 0; NULL != (section = GetSectionHeader(i)); i++) { | |
115 // Don't use the virtual RVAToAddr. | |
116 PBYTE start = reinterpret_cast<PBYTE>( | |
117 PEImage::RVAToAddr(section->VirtualAddress)); | |
118 | |
119 DWORD size = section->Misc.VirtualSize; | |
120 | |
121 if ((start <= target) && (start + size > target)) | |
122 return section; | |
123 } | |
124 | |
125 return NULL; | |
126 } | |
127 | |
128 PIMAGE_SECTION_HEADER PEImage::GetImageSectionHeaderByName( | |
129 LPCSTR section_name) const { | |
130 if (NULL == section_name) | |
131 return NULL; | |
132 | |
133 PIMAGE_SECTION_HEADER ret = NULL; | |
134 int num_sections = GetNumSections(); | |
135 | |
136 for (int i = 0; i < num_sections; i++) { | |
137 PIMAGE_SECTION_HEADER section = GetSectionHeader(i); | |
138 if (0 == _strnicmp(reinterpret_cast<LPCSTR>(section->Name), section_name, | |
139 sizeof(section->Name))) { | |
140 ret = section; | |
141 break; | |
142 } | |
143 } | |
144 | |
145 return ret; | |
146 } | |
147 | |
148 PDWORD PEImage::GetExportEntry(LPCSTR name) const { | |
149 PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory(); | |
150 | |
151 if (NULL == exports) | |
152 return NULL; | |
153 | |
154 WORD ordinal = 0; | |
155 if (!GetProcOrdinal(name, &ordinal)) | |
156 return NULL; | |
157 | |
158 PDWORD functions = reinterpret_cast<PDWORD>( | |
159 RVAToAddr(exports->AddressOfFunctions)); | |
160 | |
161 return functions + ordinal - exports->Base; | |
162 } | |
163 | |
164 FARPROC PEImage::GetProcAddress(LPCSTR function_name) const { | |
165 PDWORD export_entry = GetExportEntry(function_name); | |
166 if (NULL == export_entry) | |
167 return NULL; | |
168 | |
169 PBYTE function = reinterpret_cast<PBYTE>(RVAToAddr(*export_entry)); | |
170 | |
171 PBYTE exports = reinterpret_cast<PBYTE>( | |
172 GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT)); | |
173 DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT); | |
174 | |
175 // Check for forwarded exports as a special case. | |
176 if (exports <= function && exports + size > function) | |
177 #pragma warning(push) | |
178 #pragma warning(disable: 4312) | |
179 // This cast generates a warning because it is 32 bit specific. | |
180 return reinterpret_cast<FARPROC>(0xFFFFFFFF); | |
181 #pragma warning(pop) | |
182 | |
183 return reinterpret_cast<FARPROC>(function); | |
184 } | |
185 | |
186 bool PEImage::GetProcOrdinal(LPCSTR function_name, WORD *ordinal) const { | |
187 if (NULL == ordinal) | |
188 return false; | |
189 | |
190 PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory(); | |
191 | |
192 if (NULL == exports) | |
193 return false; | |
194 | |
195 if (IsOrdinal(function_name)) { | |
196 *ordinal = ToOrdinal(function_name); | |
197 } else { | |
198 PDWORD names = reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfNames)); | |
199 PDWORD lower = names; | |
200 PDWORD upper = names + exports->NumberOfNames; | |
201 int cmp = -1; | |
202 | |
203 // Binary Search for the name. | |
204 while (lower != upper) { | |
205 PDWORD middle = lower + (upper - lower) / 2; | |
206 LPCSTR name = reinterpret_cast<LPCSTR>(RVAToAddr(*middle)); | |
207 | |
208 // This may be called by sandbox before MSVCRT dll loads, so can't use | |
209 // CRT function here. | |
210 cmp = StrCmpByByte(function_name, name); | |
211 | |
212 if (cmp == 0) { | |
213 lower = middle; | |
214 break; | |
215 } | |
216 | |
217 if (cmp > 0) | |
218 lower = middle + 1; | |
219 else | |
220 upper = middle; | |
221 } | |
222 | |
223 if (cmp != 0) | |
224 return false; | |
225 | |
226 | |
227 PWORD ordinals = reinterpret_cast<PWORD>( | |
228 RVAToAddr(exports->AddressOfNameOrdinals)); | |
229 | |
230 *ordinal = ordinals[lower - names] + static_cast<WORD>(exports->Base); | |
231 } | |
232 | |
233 return true; | |
234 } | |
235 | |
236 bool PEImage::EnumSections(EnumSectionsFunction callback, PVOID cookie) const { | |
237 PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); | |
238 UINT num_sections = nt_headers->FileHeader.NumberOfSections; | |
239 PIMAGE_SECTION_HEADER section = GetSectionHeader(0); | |
240 | |
241 for (UINT i = 0; i < num_sections; i++, section++) { | |
242 PVOID section_start = RVAToAddr(section->VirtualAddress); | |
243 DWORD size = section->Misc.VirtualSize; | |
244 | |
245 if (!callback(*this, section, section_start, size, cookie)) | |
246 return false; | |
247 } | |
248 | |
249 return true; | |
250 } | |
251 | |
252 bool PEImage::EnumExports(EnumExportsFunction callback, PVOID cookie) const { | |
253 PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT); | |
254 DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT); | |
255 | |
256 // Check if there are any exports at all. | |
257 if (NULL == directory || 0 == size) | |
258 return true; | |
259 | |
260 PIMAGE_EXPORT_DIRECTORY exports = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>( | |
261 directory); | |
262 UINT ordinal_base = exports->Base; | |
263 UINT num_funcs = exports->NumberOfFunctions; | |
264 UINT num_names = exports->NumberOfNames; | |
265 PDWORD functions = reinterpret_cast<PDWORD>(RVAToAddr( | |
266 exports->AddressOfFunctions)); | |
267 PDWORD names = reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfNames)); | |
268 PWORD ordinals = reinterpret_cast<PWORD>(RVAToAddr( | |
269 exports->AddressOfNameOrdinals)); | |
270 | |
271 for (UINT count = 0; count < num_funcs; count++) { | |
272 PVOID func = RVAToAddr(functions[count]); | |
273 if (NULL == func) | |
274 continue; | |
275 | |
276 // Check for a name. | |
277 LPCSTR name = NULL; | |
278 UINT hint; | |
279 for (hint = 0; hint < num_names; hint++) { | |
280 if (ordinals[hint] == count) { | |
281 name = reinterpret_cast<LPCSTR>(RVAToAddr(names[hint])); | |
282 break; | |
283 } | |
284 } | |
285 | |
286 if (name == NULL) | |
287 hint = 0; | |
288 | |
289 // Check for forwarded exports. | |
290 LPCSTR forward = NULL; | |
291 if (reinterpret_cast<char*>(func) >= reinterpret_cast<char*>(directory) && | |
292 reinterpret_cast<char*>(func) <= reinterpret_cast<char*>(directory) + | |
293 size) { | |
294 forward = reinterpret_cast<LPCSTR>(func); | |
295 func = 0; | |
296 } | |
297 | |
298 if (!callback(*this, ordinal_base + count, hint, name, func, forward, | |
299 cookie)) | |
300 return false; | |
301 } | |
302 | |
303 return true; | |
304 } | |
305 | |
306 bool PEImage::EnumRelocs(EnumRelocsFunction callback, PVOID cookie) const { | |
307 PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_BASERELOC); | |
308 DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_BASERELOC); | |
309 PIMAGE_BASE_RELOCATION base = reinterpret_cast<PIMAGE_BASE_RELOCATION>( | |
310 directory); | |
311 | |
312 if (directory == NULL || size < sizeof(IMAGE_BASE_RELOCATION)) | |
313 return true; | |
314 | |
315 while (base->SizeOfBlock) { | |
316 PWORD reloc = reinterpret_cast<PWORD>(base + 1); | |
317 UINT num_relocs = (base->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / | |
318 sizeof(WORD); | |
319 | |
320 for (UINT i = 0; i < num_relocs; i++, reloc++) { | |
321 WORD type = *reloc >> 12; | |
322 PVOID address = RVAToAddr(base->VirtualAddress + (*reloc & 0x0FFF)); | |
323 | |
324 if (!callback(*this, type, address, cookie)) | |
325 return false; | |
326 } | |
327 | |
328 base = reinterpret_cast<PIMAGE_BASE_RELOCATION>( | |
329 reinterpret_cast<char*>(base) + base->SizeOfBlock); | |
330 } | |
331 | |
332 return true; | |
333 } | |
334 | |
335 bool PEImage::EnumImportChunks(EnumImportChunksFunction callback, | |
336 PVOID cookie) const { | |
337 DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_IMPORT); | |
338 PIMAGE_IMPORT_DESCRIPTOR import = GetFirstImportChunk(); | |
339 | |
340 if (import == NULL || size < sizeof(IMAGE_IMPORT_DESCRIPTOR)) | |
341 return true; | |
342 | |
343 for (; import->FirstThunk; import++) { | |
344 LPCSTR module_name = reinterpret_cast<LPCSTR>(RVAToAddr(import->Name)); | |
345 PIMAGE_THUNK_DATA name_table = reinterpret_cast<PIMAGE_THUNK_DATA>( | |
346 RVAToAddr(import->OriginalFirstThunk)); | |
347 PIMAGE_THUNK_DATA iat = reinterpret_cast<PIMAGE_THUNK_DATA>( | |
348 RVAToAddr(import->FirstThunk)); | |
349 | |
350 if (!callback(*this, module_name, name_table, iat, cookie)) | |
351 return false; | |
352 } | |
353 | |
354 return true; | |
355 } | |
356 | |
357 bool PEImage::EnumOneImportChunk(EnumImportsFunction callback, | |
358 LPCSTR module_name, | |
359 PIMAGE_THUNK_DATA name_table, | |
360 PIMAGE_THUNK_DATA iat, PVOID cookie) const { | |
361 if (NULL == name_table) | |
362 return false; | |
363 | |
364 for (; name_table && name_table->u1.Ordinal; name_table++, iat++) { | |
365 LPCSTR name = NULL; | |
366 WORD ordinal = 0; | |
367 WORD hint = 0; | |
368 | |
369 if (IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) { | |
370 ordinal = static_cast<WORD>(IMAGE_ORDINAL32(name_table->u1.Ordinal)); | |
371 } else { | |
372 PIMAGE_IMPORT_BY_NAME import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>( | |
373 RVAToAddr(name_table->u1.ForwarderString)); | |
374 | |
375 hint = import->Hint; | |
376 name = reinterpret_cast<LPCSTR>(&import->Name); | |
377 } | |
378 | |
379 if (!callback(*this, module_name, ordinal, name, hint, iat, cookie)) | |
380 return false; | |
381 } | |
382 | |
383 return true; | |
384 } | |
385 | |
386 bool PEImage::EnumAllImports(EnumImportsFunction callback, PVOID cookie) const { | |
387 EnumAllImportsStorage temp = { callback, cookie }; | |
388 return EnumImportChunks(ProcessImportChunk, &temp); | |
389 } | |
390 | |
391 bool PEImage::EnumDelayImportChunks(EnumDelayImportChunksFunction callback, | |
392 PVOID cookie) const { | |
393 PVOID directory = GetImageDirectoryEntryAddr( | |
394 IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT); | |
395 DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT); | |
396 PImgDelayDescr delay_descriptor = reinterpret_cast<PImgDelayDescr>(directory); | |
397 | |
398 if (directory == NULL || size == 0) | |
399 return true; | |
400 | |
401 for (; delay_descriptor->rvaHmod; delay_descriptor++) { | |
402 PIMAGE_THUNK_DATA name_table; | |
403 PIMAGE_THUNK_DATA iat; | |
404 PIMAGE_THUNK_DATA bound_iat; // address of the optional bound IAT | |
405 PIMAGE_THUNK_DATA unload_iat; // address of optional copy of original IAT | |
406 LPCSTR module_name; | |
407 | |
408 // check if VC7-style imports, using RVAs instead of | |
409 // VC6-style addresses. | |
410 bool rvas = (delay_descriptor->grAttrs & dlattrRva) != 0; | |
411 | |
412 if (rvas) { | |
413 module_name = reinterpret_cast<LPCSTR>( | |
414 RVAToAddr(delay_descriptor->rvaDLLName)); | |
415 name_table = reinterpret_cast<PIMAGE_THUNK_DATA>( | |
416 RVAToAddr(delay_descriptor->rvaINT)); | |
417 iat = reinterpret_cast<PIMAGE_THUNK_DATA>( | |
418 RVAToAddr(delay_descriptor->rvaIAT)); | |
419 bound_iat = reinterpret_cast<PIMAGE_THUNK_DATA>( | |
420 RVAToAddr(delay_descriptor->rvaBoundIAT)); | |
421 unload_iat = reinterpret_cast<PIMAGE_THUNK_DATA>( | |
422 RVAToAddr(delay_descriptor->rvaUnloadIAT)); | |
423 } else { | |
424 #pragma warning(push) | |
425 #pragma warning(disable: 4312) | |
426 // These casts generate warnings because they are 32 bit specific. | |
427 module_name = reinterpret_cast<LPCSTR>(delay_descriptor->rvaDLLName); | |
428 name_table = reinterpret_cast<PIMAGE_THUNK_DATA>( | |
429 delay_descriptor->rvaINT); | |
430 iat = reinterpret_cast<PIMAGE_THUNK_DATA>(delay_descriptor->rvaIAT); | |
431 bound_iat = reinterpret_cast<PIMAGE_THUNK_DATA>( | |
432 delay_descriptor->rvaBoundIAT); | |
433 unload_iat = reinterpret_cast<PIMAGE_THUNK_DATA>( | |
434 delay_descriptor->rvaUnloadIAT); | |
435 #pragma warning(pop) | |
436 } | |
437 | |
438 if (!callback(*this, delay_descriptor, module_name, name_table, iat, | |
439 bound_iat, unload_iat, cookie)) | |
440 return false; | |
441 } | |
442 | |
443 return true; | |
444 } | |
445 | |
446 bool PEImage::EnumOneDelayImportChunk(EnumImportsFunction callback, | |
447 PImgDelayDescr delay_descriptor, | |
448 LPCSTR module_name, | |
449 PIMAGE_THUNK_DATA name_table, | |
450 PIMAGE_THUNK_DATA iat, | |
451 PIMAGE_THUNK_DATA bound_iat, | |
452 PIMAGE_THUNK_DATA unload_iat, | |
453 PVOID cookie) const { | |
454 UNREFERENCED_PARAMETER(bound_iat); | |
455 UNREFERENCED_PARAMETER(unload_iat); | |
456 | |
457 for (; name_table->u1.Ordinal; name_table++, iat++) { | |
458 LPCSTR name = NULL; | |
459 WORD ordinal = 0; | |
460 WORD hint = 0; | |
461 | |
462 if (IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) { | |
463 ordinal = static_cast<WORD>(IMAGE_ORDINAL32(name_table->u1.Ordinal)); | |
464 } else { | |
465 PIMAGE_IMPORT_BY_NAME import; | |
466 bool rvas = (delay_descriptor->grAttrs & dlattrRva) != 0; | |
467 | |
468 if (rvas) { | |
469 import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>( | |
470 RVAToAddr(name_table->u1.ForwarderString)); | |
471 } else { | |
472 #pragma warning(push) | |
473 #pragma warning(disable: 4312) | |
474 // This cast generates a warning because it is 32 bit specific. | |
475 import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>( | |
476 name_table->u1.ForwarderString); | |
477 #pragma warning(pop) | |
478 } | |
479 | |
480 hint = import->Hint; | |
481 name = reinterpret_cast<LPCSTR>(&import->Name); | |
482 } | |
483 | |
484 if (!callback(*this, module_name, ordinal, name, hint, iat, cookie)) | |
485 return false; | |
486 } | |
487 | |
488 return true; | |
489 } | |
490 | |
491 bool PEImage::EnumAllDelayImports(EnumImportsFunction callback, | |
492 PVOID cookie) const { | |
493 EnumAllImportsStorage temp = { callback, cookie }; | |
494 return EnumDelayImportChunks(ProcessDelayImportChunk, &temp); | |
495 } | |
496 | |
497 bool PEImage::VerifyMagic() const { | |
498 PIMAGE_DOS_HEADER dos_header = GetDosHeader(); | |
499 | |
500 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) | |
501 return false; | |
502 | |
503 PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); | |
504 | |
505 if (nt_headers->Signature != IMAGE_NT_SIGNATURE) | |
506 return false; | |
507 | |
508 if (nt_headers->FileHeader.SizeOfOptionalHeader != | |
509 sizeof(IMAGE_OPTIONAL_HEADER)) | |
510 return false; | |
511 | |
512 if (nt_headers->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC) | |
513 return false; | |
514 | |
515 return true; | |
516 } | |
517 | |
518 bool PEImage::ImageRVAToOnDiskOffset(DWORD rva, DWORD *on_disk_offset) const { | |
519 LPVOID address = RVAToAddr(rva); | |
520 return ImageAddrToOnDiskOffset(address, on_disk_offset); | |
521 } | |
522 | |
523 bool PEImage::ImageAddrToOnDiskOffset(LPVOID address, | |
524 DWORD *on_disk_offset) const { | |
525 if (NULL == address) | |
526 return false; | |
527 | |
528 // Get the section that this address belongs to. | |
529 PIMAGE_SECTION_HEADER section_header = GetImageSectionFromAddr(address); | |
530 if (NULL == section_header) | |
531 return false; | |
532 | |
533 #pragma warning(push) | |
534 #pragma warning(disable: 4311) | |
535 // These casts generate warnings because they are 32 bit specific. | |
536 // Don't follow the virtual RVAToAddr, use the one on the base. | |
537 DWORD offset_within_section = reinterpret_cast<DWORD>(address) - | |
538 reinterpret_cast<DWORD>(PEImage::RVAToAddr( | |
539 section_header->VirtualAddress)); | |
540 #pragma warning(pop) | |
541 | |
542 *on_disk_offset = section_header->PointerToRawData + offset_within_section; | |
543 return true; | |
544 } | |
545 | |
546 PVOID PEImage::RVAToAddr(DWORD rva) const { | |
547 if (rva == 0) | |
548 return NULL; | |
549 | |
550 return reinterpret_cast<char*>(module_) + rva; | |
551 } | |
552 | |
553 PVOID PEImageAsData::RVAToAddr(DWORD rva) const { | |
554 if (rva == 0) | |
555 return NULL; | |
556 | |
557 PVOID in_memory = PEImage::RVAToAddr(rva); | |
558 DWORD dummy; | |
559 | |
560 if (!ImageAddrToOnDiskOffset(in_memory, &dummy)) | |
561 return NULL; | |
562 | |
563 return in_memory; | |
564 } | |
OLD | NEW |