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