Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(445)

Side by Side Diff: base/win/pe_image.cc

Issue 1446363003: Deleted OS_WIN and all Windows specific files from base. (Closed) Base URL: https://github.com/domokit/mojo.git@base_tests
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/win/pe_image.h ('k') | base/win/pe_image_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 // TODO(jschuh): crbug.com/167707 Make sure this code works on 64-bit.
14
15 // Structure to perform imports enumerations.
16 struct EnumAllImportsStorage {
17 PEImage::EnumImportsFunction callback;
18 PVOID cookie;
19 };
20
21 namespace {
22
23 // PdbInfo Signature
24 const DWORD kPdbInfoSignature = 'SDSR';
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 struct PdbInfo {
42 DWORD Signature;
43 GUID Guid;
44 DWORD Age;
45 char PdbFileName[1];
46 };
47 } // namespace
48
49 // Callback used to enumerate imports. See EnumImportChunksFunction.
50 bool ProcessImportChunk(const PEImage &image, LPCSTR module,
51 PIMAGE_THUNK_DATA name_table,
52 PIMAGE_THUNK_DATA iat, PVOID cookie) {
53 EnumAllImportsStorage &storage = *reinterpret_cast<EnumAllImportsStorage*>(
54 cookie);
55
56 return image.EnumOneImportChunk(storage.callback, module, name_table, iat,
57 storage.cookie);
58 }
59
60 // Callback used to enumerate delay imports. See EnumDelayImportChunksFunction.
61 bool ProcessDelayImportChunk(const PEImage &image,
62 PImgDelayDescr delay_descriptor,
63 LPCSTR module, PIMAGE_THUNK_DATA name_table,
64 PIMAGE_THUNK_DATA iat, PIMAGE_THUNK_DATA bound_iat,
65 PIMAGE_THUNK_DATA unload_iat, PVOID cookie) {
66 EnumAllImportsStorage &storage = *reinterpret_cast<EnumAllImportsStorage*>(
67 cookie);
68
69 return image.EnumOneDelayImportChunk(storage.callback, delay_descriptor,
70 module, name_table, iat, bound_iat,
71 unload_iat, storage.cookie);
72 }
73
74 void PEImage::set_module(HMODULE module) {
75 module_ = module;
76 }
77
78 PIMAGE_DOS_HEADER PEImage::GetDosHeader() const {
79 return reinterpret_cast<PIMAGE_DOS_HEADER>(module_);
80 }
81
82 PIMAGE_NT_HEADERS PEImage::GetNTHeaders() const {
83 PIMAGE_DOS_HEADER dos_header = GetDosHeader();
84
85 return reinterpret_cast<PIMAGE_NT_HEADERS>(
86 reinterpret_cast<char*>(dos_header) + dos_header->e_lfanew);
87 }
88
89 PIMAGE_SECTION_HEADER PEImage::GetSectionHeader(UINT section) const {
90 PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
91 PIMAGE_SECTION_HEADER first_section = IMAGE_FIRST_SECTION(nt_headers);
92
93 if (section < nt_headers->FileHeader.NumberOfSections)
94 return first_section + section;
95 else
96 return NULL;
97 }
98
99 WORD PEImage::GetNumSections() const {
100 return GetNTHeaders()->FileHeader.NumberOfSections;
101 }
102
103 DWORD PEImage::GetImageDirectoryEntrySize(UINT directory) const {
104 PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
105
106 return nt_headers->OptionalHeader.DataDirectory[directory].Size;
107 }
108
109 PVOID PEImage::GetImageDirectoryEntryAddr(UINT directory) const {
110 PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
111
112 return RVAToAddr(
113 nt_headers->OptionalHeader.DataDirectory[directory].VirtualAddress);
114 }
115
116 PIMAGE_SECTION_HEADER PEImage::GetImageSectionFromAddr(PVOID address) const {
117 PBYTE target = reinterpret_cast<PBYTE>(address);
118 PIMAGE_SECTION_HEADER section;
119
120 for (UINT i = 0; NULL != (section = GetSectionHeader(i)); i++) {
121 // Don't use the virtual RVAToAddr.
122 PBYTE start = reinterpret_cast<PBYTE>(
123 PEImage::RVAToAddr(section->VirtualAddress));
124
125 DWORD size = section->Misc.VirtualSize;
126
127 if ((start <= target) && (start + size > target))
128 return section;
129 }
130
131 return NULL;
132 }
133
134 PIMAGE_SECTION_HEADER PEImage::GetImageSectionHeaderByName(
135 LPCSTR section_name) const {
136 if (NULL == section_name)
137 return NULL;
138
139 PIMAGE_SECTION_HEADER ret = NULL;
140 int num_sections = GetNumSections();
141
142 for (int i = 0; i < num_sections; i++) {
143 PIMAGE_SECTION_HEADER section = GetSectionHeader(i);
144 if (0 == _strnicmp(reinterpret_cast<LPCSTR>(section->Name), section_name,
145 sizeof(section->Name))) {
146 ret = section;
147 break;
148 }
149 }
150
151 return ret;
152 }
153
154 bool PEImage::GetDebugId(LPGUID guid, LPDWORD age) const {
155 if (NULL == guid || NULL == age) {
156 return false;
157 }
158
159 DWORD debug_directory_size =
160 GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_DEBUG);
161 PIMAGE_DEBUG_DIRECTORY debug_directory =
162 reinterpret_cast<PIMAGE_DEBUG_DIRECTORY>(
163 GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_DEBUG));
164
165 size_t directory_count =
166 debug_directory_size / sizeof(IMAGE_DEBUG_DIRECTORY);
167
168 for (size_t index = 0; index < directory_count; ++index) {
169 if (debug_directory[index].Type == IMAGE_DEBUG_TYPE_CODEVIEW) {
170 PdbInfo* pdb_info = reinterpret_cast<PdbInfo*>(
171 RVAToAddr(debug_directory[index].AddressOfRawData));
172 if (pdb_info->Signature != kPdbInfoSignature) {
173 // Unsupported PdbInfo signature
174 return false;
175 }
176 *guid = pdb_info->Guid;
177 *age = pdb_info->Age;
178 return true;
179 }
180 }
181 return false;
182 }
183
184 PDWORD PEImage::GetExportEntry(LPCSTR name) const {
185 PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory();
186
187 if (NULL == exports)
188 return NULL;
189
190 WORD ordinal = 0;
191 if (!GetProcOrdinal(name, &ordinal))
192 return NULL;
193
194 PDWORD functions = reinterpret_cast<PDWORD>(
195 RVAToAddr(exports->AddressOfFunctions));
196
197 return functions + ordinal - exports->Base;
198 }
199
200 FARPROC PEImage::GetProcAddress(LPCSTR function_name) const {
201 PDWORD export_entry = GetExportEntry(function_name);
202 if (NULL == export_entry)
203 return NULL;
204
205 PBYTE function = reinterpret_cast<PBYTE>(RVAToAddr(*export_entry));
206
207 PBYTE exports = reinterpret_cast<PBYTE>(
208 GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT));
209 DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT);
210
211 // Check for forwarded exports as a special case.
212 if (exports <= function && exports + size > function)
213 #pragma warning(push)
214 #pragma warning(disable: 4312)
215 // This cast generates a warning because it is 32 bit specific.
216 return reinterpret_cast<FARPROC>(0xFFFFFFFF);
217 #pragma warning(pop)
218
219 return reinterpret_cast<FARPROC>(function);
220 }
221
222 bool PEImage::GetProcOrdinal(LPCSTR function_name, WORD *ordinal) const {
223 if (NULL == ordinal)
224 return false;
225
226 PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory();
227
228 if (NULL == exports)
229 return false;
230
231 if (IsOrdinal(function_name)) {
232 *ordinal = ToOrdinal(function_name);
233 } else {
234 PDWORD names = reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfNames));
235 PDWORD lower = names;
236 PDWORD upper = names + exports->NumberOfNames;
237 int cmp = -1;
238
239 // Binary Search for the name.
240 while (lower != upper) {
241 PDWORD middle = lower + (upper - lower) / 2;
242 LPCSTR name = reinterpret_cast<LPCSTR>(RVAToAddr(*middle));
243
244 // This may be called by sandbox before MSVCRT dll loads, so can't use
245 // CRT function here.
246 cmp = StrCmpByByte(function_name, name);
247
248 if (cmp == 0) {
249 lower = middle;
250 break;
251 }
252
253 if (cmp > 0)
254 lower = middle + 1;
255 else
256 upper = middle;
257 }
258
259 if (cmp != 0)
260 return false;
261
262
263 PWORD ordinals = reinterpret_cast<PWORD>(
264 RVAToAddr(exports->AddressOfNameOrdinals));
265
266 *ordinal = ordinals[lower - names] + static_cast<WORD>(exports->Base);
267 }
268
269 return true;
270 }
271
272 bool PEImage::EnumSections(EnumSectionsFunction callback, PVOID cookie) const {
273 PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
274 UINT num_sections = nt_headers->FileHeader.NumberOfSections;
275 PIMAGE_SECTION_HEADER section = GetSectionHeader(0);
276
277 for (UINT i = 0; i < num_sections; i++, section++) {
278 PVOID section_start = RVAToAddr(section->VirtualAddress);
279 DWORD size = section->Misc.VirtualSize;
280
281 if (!callback(*this, section, section_start, size, cookie))
282 return false;
283 }
284
285 return true;
286 }
287
288 bool PEImage::EnumExports(EnumExportsFunction callback, PVOID cookie) const {
289 PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT);
290 DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT);
291
292 // Check if there are any exports at all.
293 if (NULL == directory || 0 == size)
294 return true;
295
296 PIMAGE_EXPORT_DIRECTORY exports = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(
297 directory);
298 UINT ordinal_base = exports->Base;
299 UINT num_funcs = exports->NumberOfFunctions;
300 UINT num_names = exports->NumberOfNames;
301 PDWORD functions = reinterpret_cast<PDWORD>(RVAToAddr(
302 exports->AddressOfFunctions));
303 PDWORD names = reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfNames));
304 PWORD ordinals = reinterpret_cast<PWORD>(RVAToAddr(
305 exports->AddressOfNameOrdinals));
306
307 for (UINT count = 0; count < num_funcs; count++) {
308 PVOID func = RVAToAddr(functions[count]);
309 if (NULL == func)
310 continue;
311
312 // Check for a name.
313 LPCSTR name = NULL;
314 UINT hint;
315 for (hint = 0; hint < num_names; hint++) {
316 if (ordinals[hint] == count) {
317 name = reinterpret_cast<LPCSTR>(RVAToAddr(names[hint]));
318 break;
319 }
320 }
321
322 if (name == NULL)
323 hint = 0;
324
325 // Check for forwarded exports.
326 LPCSTR forward = NULL;
327 if (reinterpret_cast<char*>(func) >= reinterpret_cast<char*>(directory) &&
328 reinterpret_cast<char*>(func) <= reinterpret_cast<char*>(directory) +
329 size) {
330 forward = reinterpret_cast<LPCSTR>(func);
331 func = 0;
332 }
333
334 if (!callback(*this, ordinal_base + count, hint, name, func, forward,
335 cookie))
336 return false;
337 }
338
339 return true;
340 }
341
342 bool PEImage::EnumRelocs(EnumRelocsFunction callback, PVOID cookie) const {
343 PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_BASERELOC);
344 DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_BASERELOC);
345 PIMAGE_BASE_RELOCATION base = reinterpret_cast<PIMAGE_BASE_RELOCATION>(
346 directory);
347
348 if (!directory)
349 return true;
350
351 while (size >= sizeof(IMAGE_BASE_RELOCATION) && base->SizeOfBlock &&
352 size >= base->SizeOfBlock) {
353 PWORD reloc = reinterpret_cast<PWORD>(base + 1);
354 UINT num_relocs = (base->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) /
355 sizeof(WORD);
356
357 for (UINT i = 0; i < num_relocs; i++, reloc++) {
358 WORD type = *reloc >> 12;
359 PVOID address = RVAToAddr(base->VirtualAddress + (*reloc & 0x0FFF));
360
361 if (!callback(*this, type, address, cookie))
362 return false;
363 }
364
365 size -= base->SizeOfBlock;
366 base = reinterpret_cast<PIMAGE_BASE_RELOCATION>(
367 reinterpret_cast<char*>(base) + base->SizeOfBlock);
368 }
369
370 return true;
371 }
372
373 bool PEImage::EnumImportChunks(EnumImportChunksFunction callback,
374 PVOID cookie) const {
375 DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_IMPORT);
376 PIMAGE_IMPORT_DESCRIPTOR import = GetFirstImportChunk();
377
378 if (import == NULL || size < sizeof(IMAGE_IMPORT_DESCRIPTOR))
379 return true;
380
381 for (; import->FirstThunk; import++) {
382 LPCSTR module_name = reinterpret_cast<LPCSTR>(RVAToAddr(import->Name));
383 PIMAGE_THUNK_DATA name_table = reinterpret_cast<PIMAGE_THUNK_DATA>(
384 RVAToAddr(import->OriginalFirstThunk));
385 PIMAGE_THUNK_DATA iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
386 RVAToAddr(import->FirstThunk));
387
388 if (!callback(*this, module_name, name_table, iat, cookie))
389 return false;
390 }
391
392 return true;
393 }
394
395 bool PEImage::EnumOneImportChunk(EnumImportsFunction callback,
396 LPCSTR module_name,
397 PIMAGE_THUNK_DATA name_table,
398 PIMAGE_THUNK_DATA iat, PVOID cookie) const {
399 if (NULL == name_table)
400 return false;
401
402 for (; name_table && name_table->u1.Ordinal; name_table++, iat++) {
403 LPCSTR name = NULL;
404 WORD ordinal = 0;
405 WORD hint = 0;
406
407 if (IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) {
408 ordinal = static_cast<WORD>(IMAGE_ORDINAL32(name_table->u1.Ordinal));
409 } else {
410 PIMAGE_IMPORT_BY_NAME import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(
411 RVAToAddr(name_table->u1.ForwarderString));
412
413 hint = import->Hint;
414 name = reinterpret_cast<LPCSTR>(&import->Name);
415 }
416
417 if (!callback(*this, module_name, ordinal, name, hint, iat, cookie))
418 return false;
419 }
420
421 return true;
422 }
423
424 bool PEImage::EnumAllImports(EnumImportsFunction callback, PVOID cookie) const {
425 EnumAllImportsStorage temp = { callback, cookie };
426 return EnumImportChunks(ProcessImportChunk, &temp);
427 }
428
429 bool PEImage::EnumDelayImportChunks(EnumDelayImportChunksFunction callback,
430 PVOID cookie) const {
431 PVOID directory = GetImageDirectoryEntryAddr(
432 IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
433 DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
434 PImgDelayDescr delay_descriptor = reinterpret_cast<PImgDelayDescr>(directory);
435
436 if (directory == NULL || size == 0)
437 return true;
438
439 for (; delay_descriptor->rvaHmod; delay_descriptor++) {
440 PIMAGE_THUNK_DATA name_table;
441 PIMAGE_THUNK_DATA iat;
442 PIMAGE_THUNK_DATA bound_iat; // address of the optional bound IAT
443 PIMAGE_THUNK_DATA unload_iat; // address of optional copy of original IAT
444 LPCSTR module_name;
445
446 // check if VC7-style imports, using RVAs instead of
447 // VC6-style addresses.
448 bool rvas = (delay_descriptor->grAttrs & dlattrRva) != 0;
449
450 if (rvas) {
451 module_name = reinterpret_cast<LPCSTR>(
452 RVAToAddr(delay_descriptor->rvaDLLName));
453 name_table = reinterpret_cast<PIMAGE_THUNK_DATA>(
454 RVAToAddr(delay_descriptor->rvaINT));
455 iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
456 RVAToAddr(delay_descriptor->rvaIAT));
457 bound_iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
458 RVAToAddr(delay_descriptor->rvaBoundIAT));
459 unload_iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
460 RVAToAddr(delay_descriptor->rvaUnloadIAT));
461 } else {
462 #pragma warning(push)
463 #pragma warning(disable: 4312)
464 // These casts generate warnings because they are 32 bit specific.
465 module_name = reinterpret_cast<LPCSTR>(delay_descriptor->rvaDLLName);
466 name_table = reinterpret_cast<PIMAGE_THUNK_DATA>(
467 delay_descriptor->rvaINT);
468 iat = reinterpret_cast<PIMAGE_THUNK_DATA>(delay_descriptor->rvaIAT);
469 bound_iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
470 delay_descriptor->rvaBoundIAT);
471 unload_iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
472 delay_descriptor->rvaUnloadIAT);
473 #pragma warning(pop)
474 }
475
476 if (!callback(*this, delay_descriptor, module_name, name_table, iat,
477 bound_iat, unload_iat, cookie))
478 return false;
479 }
480
481 return true;
482 }
483
484 bool PEImage::EnumOneDelayImportChunk(EnumImportsFunction callback,
485 PImgDelayDescr delay_descriptor,
486 LPCSTR module_name,
487 PIMAGE_THUNK_DATA name_table,
488 PIMAGE_THUNK_DATA iat,
489 PIMAGE_THUNK_DATA bound_iat,
490 PIMAGE_THUNK_DATA unload_iat,
491 PVOID cookie) const {
492 UNREFERENCED_PARAMETER(bound_iat);
493 UNREFERENCED_PARAMETER(unload_iat);
494
495 for (; name_table->u1.Ordinal; name_table++, iat++) {
496 LPCSTR name = NULL;
497 WORD ordinal = 0;
498 WORD hint = 0;
499
500 if (IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) {
501 ordinal = static_cast<WORD>(IMAGE_ORDINAL32(name_table->u1.Ordinal));
502 } else {
503 PIMAGE_IMPORT_BY_NAME import;
504 bool rvas = (delay_descriptor->grAttrs & dlattrRva) != 0;
505
506 if (rvas) {
507 import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(
508 RVAToAddr(name_table->u1.ForwarderString));
509 } else {
510 #pragma warning(push)
511 #pragma warning(disable: 4312)
512 // This cast generates a warning because it is 32 bit specific.
513 import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(
514 name_table->u1.ForwarderString);
515 #pragma warning(pop)
516 }
517
518 hint = import->Hint;
519 name = reinterpret_cast<LPCSTR>(&import->Name);
520 }
521
522 if (!callback(*this, module_name, ordinal, name, hint, iat, cookie))
523 return false;
524 }
525
526 return true;
527 }
528
529 bool PEImage::EnumAllDelayImports(EnumImportsFunction callback,
530 PVOID cookie) const {
531 EnumAllImportsStorage temp = { callback, cookie };
532 return EnumDelayImportChunks(ProcessDelayImportChunk, &temp);
533 }
534
535 bool PEImage::VerifyMagic() const {
536 PIMAGE_DOS_HEADER dos_header = GetDosHeader();
537
538 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
539 return false;
540
541 PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
542
543 if (nt_headers->Signature != IMAGE_NT_SIGNATURE)
544 return false;
545
546 if (nt_headers->FileHeader.SizeOfOptionalHeader !=
547 sizeof(IMAGE_OPTIONAL_HEADER))
548 return false;
549
550 if (nt_headers->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
551 return false;
552
553 return true;
554 }
555
556 bool PEImage::ImageRVAToOnDiskOffset(DWORD rva, DWORD *on_disk_offset) const {
557 LPVOID address = RVAToAddr(rva);
558 return ImageAddrToOnDiskOffset(address, on_disk_offset);
559 }
560
561 bool PEImage::ImageAddrToOnDiskOffset(LPVOID address,
562 DWORD *on_disk_offset) const {
563 if (NULL == address)
564 return false;
565
566 // Get the section that this address belongs to.
567 PIMAGE_SECTION_HEADER section_header = GetImageSectionFromAddr(address);
568 if (NULL == section_header)
569 return false;
570
571 // Don't follow the virtual RVAToAddr, use the one on the base.
572 DWORD offset_within_section =
573 static_cast<DWORD>(reinterpret_cast<uintptr_t>(address)) -
574 static_cast<DWORD>(reinterpret_cast<uintptr_t>(
575 PEImage::RVAToAddr(section_header->VirtualAddress)));
576
577 *on_disk_offset = section_header->PointerToRawData + offset_within_section;
578 return true;
579 }
580
581 PVOID PEImage::RVAToAddr(DWORD rva) const {
582 if (rva == 0)
583 return NULL;
584
585 return reinterpret_cast<char*>(module_) + rva;
586 }
587
588 PVOID PEImageAsData::RVAToAddr(DWORD rva) const {
589 if (rva == 0)
590 return NULL;
591
592 PVOID in_memory = PEImage::RVAToAddr(rva);
593 DWORD disk_offset;
594
595 if (!ImageAddrToOnDiskOffset(in_memory, &disk_offset))
596 return NULL;
597
598 return PEImage::RVAToAddr(disk_offset);
599 }
600
601 } // namespace win
602 } // namespace base
OLDNEW
« no previous file with comments | « base/win/pe_image.h ('k') | base/win/pe_image_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698