xref: /aosp_15_r20/external/cronet/base/win/pe_image.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2010 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker // This file implements PEImage, a generic class to manipulate PE files.
6*6777b538SAndroid Build Coastguard Worker // This file was adapted from GreenBorder's Code.
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include "base/win/pe_image.h"
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include <delayimp.h>
11*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
12*6777b538SAndroid Build Coastguard Worker #include <set>
13*6777b538SAndroid Build Coastguard Worker #include <string>
14*6777b538SAndroid Build Coastguard Worker 
15*6777b538SAndroid Build Coastguard Worker #include "base/no_destructor.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/win/current_module.h"
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker namespace base {
19*6777b538SAndroid Build Coastguard Worker namespace win {
20*6777b538SAndroid Build Coastguard Worker 
21*6777b538SAndroid Build Coastguard Worker // Structure to perform imports enumerations.
22*6777b538SAndroid Build Coastguard Worker struct EnumAllImportsStorage {
23*6777b538SAndroid Build Coastguard Worker   PEImage::EnumImportsFunction callback;
24*6777b538SAndroid Build Coastguard Worker   PVOID cookie;
25*6777b538SAndroid Build Coastguard Worker };
26*6777b538SAndroid Build Coastguard Worker 
27*6777b538SAndroid Build Coastguard Worker namespace {
28*6777b538SAndroid Build Coastguard Worker 
29*6777b538SAndroid Build Coastguard Worker // PdbInfo Signature
30*6777b538SAndroid Build Coastguard Worker const DWORD kPdbInfoSignature = 'SDSR';
31*6777b538SAndroid Build Coastguard Worker 
32*6777b538SAndroid Build Coastguard Worker // Compare two strings byte by byte on an unsigned basis.
33*6777b538SAndroid Build Coastguard Worker //   if s1 == s2, return 0
34*6777b538SAndroid Build Coastguard Worker //   if s1 < s2, return negative
35*6777b538SAndroid Build Coastguard Worker //   if s1 > s2, return positive
36*6777b538SAndroid Build Coastguard Worker // Exception if inputs are invalid.
StrCmpByByte(LPCSTR s1,LPCSTR s2)37*6777b538SAndroid Build Coastguard Worker int StrCmpByByte(LPCSTR s1, LPCSTR s2) {
38*6777b538SAndroid Build Coastguard Worker   while (*s1 != '\0' && *s1 == *s2) {
39*6777b538SAndroid Build Coastguard Worker     ++s1;
40*6777b538SAndroid Build Coastguard Worker     ++s2;
41*6777b538SAndroid Build Coastguard Worker   }
42*6777b538SAndroid Build Coastguard Worker 
43*6777b538SAndroid Build Coastguard Worker   return (*reinterpret_cast<const unsigned char*>(s1) -
44*6777b538SAndroid Build Coastguard Worker           *reinterpret_cast<const unsigned char*>(s2));
45*6777b538SAndroid Build Coastguard Worker }
46*6777b538SAndroid Build Coastguard Worker 
47*6777b538SAndroid Build Coastguard Worker struct PdbInfo {
48*6777b538SAndroid Build Coastguard Worker   DWORD Signature;
49*6777b538SAndroid Build Coastguard Worker   GUID Guid;
50*6777b538SAndroid Build Coastguard Worker   DWORD Age;
51*6777b538SAndroid Build Coastguard Worker   char PdbFileName[1];
52*6777b538SAndroid Build Coastguard Worker };
53*6777b538SAndroid Build Coastguard Worker 
54*6777b538SAndroid Build Coastguard Worker #define LDR_IS_DATAFILE(handle) (((ULONG_PTR)(handle)) & (ULONG_PTR)1)
55*6777b538SAndroid Build Coastguard Worker #define LDR_IS_IMAGEMAPPING(handle) (((ULONG_PTR)(handle)) & (ULONG_PTR)2)
56*6777b538SAndroid Build Coastguard Worker #define LDR_IS_RESOURCE(handle) \
57*6777b538SAndroid Build Coastguard Worker   (LDR_IS_IMAGEMAPPING(handle) || LDR_IS_DATAFILE(handle))
58*6777b538SAndroid Build Coastguard Worker 
59*6777b538SAndroid Build Coastguard Worker }  // namespace
60*6777b538SAndroid Build Coastguard Worker 
61*6777b538SAndroid Build Coastguard Worker // Callback used to enumerate imports. See EnumImportChunksFunction.
ProcessImportChunk(const PEImage & image,LPCSTR module,PIMAGE_THUNK_DATA name_table,PIMAGE_THUNK_DATA iat,PVOID cookie)62*6777b538SAndroid Build Coastguard Worker bool ProcessImportChunk(const PEImage& image,
63*6777b538SAndroid Build Coastguard Worker                         LPCSTR module,
64*6777b538SAndroid Build Coastguard Worker                         PIMAGE_THUNK_DATA name_table,
65*6777b538SAndroid Build Coastguard Worker                         PIMAGE_THUNK_DATA iat,
66*6777b538SAndroid Build Coastguard Worker                         PVOID cookie) {
67*6777b538SAndroid Build Coastguard Worker   EnumAllImportsStorage& storage =
68*6777b538SAndroid Build Coastguard Worker       *reinterpret_cast<EnumAllImportsStorage*>(cookie);
69*6777b538SAndroid Build Coastguard Worker 
70*6777b538SAndroid Build Coastguard Worker   return image.EnumOneImportChunk(storage.callback, module, name_table, iat,
71*6777b538SAndroid Build Coastguard Worker                                   storage.cookie);
72*6777b538SAndroid Build Coastguard Worker }
73*6777b538SAndroid Build Coastguard Worker 
74*6777b538SAndroid Build Coastguard Worker // 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,PVOID cookie)75*6777b538SAndroid Build Coastguard Worker bool ProcessDelayImportChunk(const PEImage& image,
76*6777b538SAndroid Build Coastguard Worker                              PImgDelayDescr delay_descriptor,
77*6777b538SAndroid Build Coastguard Worker                              LPCSTR module,
78*6777b538SAndroid Build Coastguard Worker                              PIMAGE_THUNK_DATA name_table,
79*6777b538SAndroid Build Coastguard Worker                              PIMAGE_THUNK_DATA iat,
80*6777b538SAndroid Build Coastguard Worker                              PVOID cookie) {
81*6777b538SAndroid Build Coastguard Worker   EnumAllImportsStorage& storage =
82*6777b538SAndroid Build Coastguard Worker       *reinterpret_cast<EnumAllImportsStorage*>(cookie);
83*6777b538SAndroid Build Coastguard Worker 
84*6777b538SAndroid Build Coastguard Worker   return image.EnumOneDelayImportChunk(storage.callback, delay_descriptor,
85*6777b538SAndroid Build Coastguard Worker                                        module, name_table, iat, storage.cookie);
86*6777b538SAndroid Build Coastguard Worker }
87*6777b538SAndroid Build Coastguard Worker 
set_module(HMODULE module)88*6777b538SAndroid Build Coastguard Worker void PEImage::set_module(HMODULE module) {
89*6777b538SAndroid Build Coastguard Worker   module_ = module;
90*6777b538SAndroid Build Coastguard Worker }
91*6777b538SAndroid Build Coastguard Worker 
GetDosHeader() const92*6777b538SAndroid Build Coastguard Worker PIMAGE_DOS_HEADER PEImage::GetDosHeader() const {
93*6777b538SAndroid Build Coastguard Worker   return reinterpret_cast<PIMAGE_DOS_HEADER>(module_);
94*6777b538SAndroid Build Coastguard Worker }
95*6777b538SAndroid Build Coastguard Worker 
GetNTHeaders() const96*6777b538SAndroid Build Coastguard Worker PIMAGE_NT_HEADERS PEImage::GetNTHeaders() const {
97*6777b538SAndroid Build Coastguard Worker   PIMAGE_DOS_HEADER dos_header = GetDosHeader();
98*6777b538SAndroid Build Coastguard Worker 
99*6777b538SAndroid Build Coastguard Worker   return reinterpret_cast<PIMAGE_NT_HEADERS>(
100*6777b538SAndroid Build Coastguard Worker       reinterpret_cast<char*>(dos_header) + dos_header->e_lfanew);
101*6777b538SAndroid Build Coastguard Worker }
102*6777b538SAndroid Build Coastguard Worker 
GetSectionHeader(WORD section) const103*6777b538SAndroid Build Coastguard Worker PIMAGE_SECTION_HEADER PEImage::GetSectionHeader(WORD section) const {
104*6777b538SAndroid Build Coastguard Worker   PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
105*6777b538SAndroid Build Coastguard Worker   PIMAGE_SECTION_HEADER first_section = IMAGE_FIRST_SECTION(nt_headers);
106*6777b538SAndroid Build Coastguard Worker 
107*6777b538SAndroid Build Coastguard Worker   if (section < nt_headers->FileHeader.NumberOfSections)
108*6777b538SAndroid Build Coastguard Worker     return first_section + section;
109*6777b538SAndroid Build Coastguard Worker   else
110*6777b538SAndroid Build Coastguard Worker     return nullptr;
111*6777b538SAndroid Build Coastguard Worker }
112*6777b538SAndroid Build Coastguard Worker 
GetNumSections() const113*6777b538SAndroid Build Coastguard Worker WORD PEImage::GetNumSections() const {
114*6777b538SAndroid Build Coastguard Worker   return GetNTHeaders()->FileHeader.NumberOfSections;
115*6777b538SAndroid Build Coastguard Worker }
116*6777b538SAndroid Build Coastguard Worker 
GetImageDirectoryEntrySize(UINT directory) const117*6777b538SAndroid Build Coastguard Worker DWORD PEImage::GetImageDirectoryEntrySize(UINT directory) const {
118*6777b538SAndroid Build Coastguard Worker   const IMAGE_DATA_DIRECTORY* const entry = GetDataDirectory(directory);
119*6777b538SAndroid Build Coastguard Worker   return entry ? entry->Size : 0;
120*6777b538SAndroid Build Coastguard Worker }
121*6777b538SAndroid Build Coastguard Worker 
GetImageDirectoryEntryAddr(UINT directory) const122*6777b538SAndroid Build Coastguard Worker PVOID PEImage::GetImageDirectoryEntryAddr(UINT directory) const {
123*6777b538SAndroid Build Coastguard Worker   const IMAGE_DATA_DIRECTORY* const entry = GetDataDirectory(directory);
124*6777b538SAndroid Build Coastguard Worker   return entry ? RVAToAddr(entry->VirtualAddress) : nullptr;
125*6777b538SAndroid Build Coastguard Worker }
126*6777b538SAndroid Build Coastguard Worker 
GetImageSectionFromAddr(PVOID address) const127*6777b538SAndroid Build Coastguard Worker PIMAGE_SECTION_HEADER PEImage::GetImageSectionFromAddr(PVOID address) const {
128*6777b538SAndroid Build Coastguard Worker   PBYTE target = reinterpret_cast<PBYTE>(address);
129*6777b538SAndroid Build Coastguard Worker   PIMAGE_SECTION_HEADER section;
130*6777b538SAndroid Build Coastguard Worker 
131*6777b538SAndroid Build Coastguard Worker   for (WORD i = 0; nullptr != (section = GetSectionHeader(i)); i++) {
132*6777b538SAndroid Build Coastguard Worker     // Don't use the virtual RVAToAddr.
133*6777b538SAndroid Build Coastguard Worker     PBYTE start =
134*6777b538SAndroid Build Coastguard Worker         reinterpret_cast<PBYTE>(PEImage::RVAToAddr(section->VirtualAddress));
135*6777b538SAndroid Build Coastguard Worker 
136*6777b538SAndroid Build Coastguard Worker     DWORD size = section->Misc.VirtualSize;
137*6777b538SAndroid Build Coastguard Worker 
138*6777b538SAndroid Build Coastguard Worker     if ((start <= target) && (start + size > target))
139*6777b538SAndroid Build Coastguard Worker       return section;
140*6777b538SAndroid Build Coastguard Worker   }
141*6777b538SAndroid Build Coastguard Worker 
142*6777b538SAndroid Build Coastguard Worker   return nullptr;
143*6777b538SAndroid Build Coastguard Worker }
144*6777b538SAndroid Build Coastguard Worker 
GetImageSectionHeaderByName(LPCSTR section_name) const145*6777b538SAndroid Build Coastguard Worker PIMAGE_SECTION_HEADER PEImage::GetImageSectionHeaderByName(
146*6777b538SAndroid Build Coastguard Worker     LPCSTR section_name) const {
147*6777b538SAndroid Build Coastguard Worker   if (section_name == nullptr)
148*6777b538SAndroid Build Coastguard Worker     return nullptr;
149*6777b538SAndroid Build Coastguard Worker 
150*6777b538SAndroid Build Coastguard Worker   WORD num_sections = GetNumSections();
151*6777b538SAndroid Build Coastguard Worker   for (WORD i = 0; i < num_sections; ++i) {
152*6777b538SAndroid Build Coastguard Worker     PIMAGE_SECTION_HEADER section = GetSectionHeader(i);
153*6777b538SAndroid Build Coastguard Worker     if (_strnicmp(reinterpret_cast<LPCSTR>(section->Name), section_name,
154*6777b538SAndroid Build Coastguard Worker                   sizeof(section->Name)) == 0) {
155*6777b538SAndroid Build Coastguard Worker       return section;
156*6777b538SAndroid Build Coastguard Worker     }
157*6777b538SAndroid Build Coastguard Worker   }
158*6777b538SAndroid Build Coastguard Worker 
159*6777b538SAndroid Build Coastguard Worker   return nullptr;
160*6777b538SAndroid Build Coastguard Worker }
161*6777b538SAndroid Build Coastguard Worker 
GetDebugId(LPGUID guid,LPDWORD age,LPCSTR * pdb_filename,size_t * pdb_filename_length) const162*6777b538SAndroid Build Coastguard Worker bool PEImage::GetDebugId(LPGUID guid,
163*6777b538SAndroid Build Coastguard Worker                          LPDWORD age,
164*6777b538SAndroid Build Coastguard Worker                          LPCSTR* pdb_filename,
165*6777b538SAndroid Build Coastguard Worker                          size_t* pdb_filename_length) const {
166*6777b538SAndroid Build Coastguard Worker   DWORD debug_directory_size =
167*6777b538SAndroid Build Coastguard Worker       GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_DEBUG);
168*6777b538SAndroid Build Coastguard Worker   PIMAGE_DEBUG_DIRECTORY debug_directory =
169*6777b538SAndroid Build Coastguard Worker       reinterpret_cast<PIMAGE_DEBUG_DIRECTORY>(
170*6777b538SAndroid Build Coastguard Worker           GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_DEBUG));
171*6777b538SAndroid Build Coastguard Worker   if (!debug_directory)
172*6777b538SAndroid Build Coastguard Worker     return false;
173*6777b538SAndroid Build Coastguard Worker 
174*6777b538SAndroid Build Coastguard Worker   size_t directory_count = debug_directory_size / sizeof(IMAGE_DEBUG_DIRECTORY);
175*6777b538SAndroid Build Coastguard Worker   for (size_t index = 0; index < directory_count; ++index) {
176*6777b538SAndroid Build Coastguard Worker     const IMAGE_DEBUG_DIRECTORY& entry = debug_directory[index];
177*6777b538SAndroid Build Coastguard Worker     if (entry.Type != IMAGE_DEBUG_TYPE_CODEVIEW)
178*6777b538SAndroid Build Coastguard Worker       continue;  // Unsupported debugging info format.
179*6777b538SAndroid Build Coastguard Worker     if (entry.SizeOfData < sizeof(PdbInfo))
180*6777b538SAndroid Build Coastguard Worker       continue;  // The data is too small to hold PDB info.
181*6777b538SAndroid Build Coastguard Worker     const PdbInfo* pdb_info =
182*6777b538SAndroid Build Coastguard Worker         reinterpret_cast<const PdbInfo*>(RVAToAddr(entry.AddressOfRawData));
183*6777b538SAndroid Build Coastguard Worker     if (!pdb_info)
184*6777b538SAndroid Build Coastguard Worker       continue;  // The data is not present in a mapped section.
185*6777b538SAndroid Build Coastguard Worker     if (pdb_info->Signature != kPdbInfoSignature)
186*6777b538SAndroid Build Coastguard Worker       continue;  // Unsupported PdbInfo signature
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker     if (guid)
189*6777b538SAndroid Build Coastguard Worker       *guid = pdb_info->Guid;
190*6777b538SAndroid Build Coastguard Worker     if (age)
191*6777b538SAndroid Build Coastguard Worker       *age = pdb_info->Age;
192*6777b538SAndroid Build Coastguard Worker     if (pdb_filename) {
193*6777b538SAndroid Build Coastguard Worker       const size_t length_max =
194*6777b538SAndroid Build Coastguard Worker           entry.SizeOfData - offsetof(PdbInfo, PdbFileName);
195*6777b538SAndroid Build Coastguard Worker       const char* eos = pdb_info->PdbFileName;
196*6777b538SAndroid Build Coastguard Worker       for (const char* const end = pdb_info->PdbFileName + length_max;
197*6777b538SAndroid Build Coastguard Worker            eos < end && *eos; ++eos)
198*6777b538SAndroid Build Coastguard Worker         ;
199*6777b538SAndroid Build Coastguard Worker       // This static_cast is safe because the loop above only increments eos,
200*6777b538SAndroid Build Coastguard Worker       // and ensures it won't wrap.
201*6777b538SAndroid Build Coastguard Worker       *pdb_filename_length = static_cast<size_t>(eos - pdb_info->PdbFileName);
202*6777b538SAndroid Build Coastguard Worker       *pdb_filename = pdb_info->PdbFileName;
203*6777b538SAndroid Build Coastguard Worker     }
204*6777b538SAndroid Build Coastguard Worker     return true;
205*6777b538SAndroid Build Coastguard Worker   }
206*6777b538SAndroid Build Coastguard Worker   return false;
207*6777b538SAndroid Build Coastguard Worker }
208*6777b538SAndroid Build Coastguard Worker 
GetExportEntry(LPCSTR name) const209*6777b538SAndroid Build Coastguard Worker PDWORD PEImage::GetExportEntry(LPCSTR name) const {
210*6777b538SAndroid Build Coastguard Worker   PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory();
211*6777b538SAndroid Build Coastguard Worker 
212*6777b538SAndroid Build Coastguard Worker   if (nullptr == exports)
213*6777b538SAndroid Build Coastguard Worker     return nullptr;
214*6777b538SAndroid Build Coastguard Worker 
215*6777b538SAndroid Build Coastguard Worker   WORD ordinal = 0;
216*6777b538SAndroid Build Coastguard Worker   if (!GetProcOrdinal(name, &ordinal))
217*6777b538SAndroid Build Coastguard Worker     return nullptr;
218*6777b538SAndroid Build Coastguard Worker 
219*6777b538SAndroid Build Coastguard Worker   PDWORD functions =
220*6777b538SAndroid Build Coastguard Worker       reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfFunctions));
221*6777b538SAndroid Build Coastguard Worker 
222*6777b538SAndroid Build Coastguard Worker   return functions + ordinal - exports->Base;
223*6777b538SAndroid Build Coastguard Worker }
224*6777b538SAndroid Build Coastguard Worker 
GetProcAddress(LPCSTR function_name) const225*6777b538SAndroid Build Coastguard Worker FARPROC PEImage::GetProcAddress(LPCSTR function_name) const {
226*6777b538SAndroid Build Coastguard Worker   PDWORD export_entry = GetExportEntry(function_name);
227*6777b538SAndroid Build Coastguard Worker   if (nullptr == export_entry)
228*6777b538SAndroid Build Coastguard Worker     return nullptr;
229*6777b538SAndroid Build Coastguard Worker 
230*6777b538SAndroid Build Coastguard Worker   PBYTE function = reinterpret_cast<PBYTE>(RVAToAddr(*export_entry));
231*6777b538SAndroid Build Coastguard Worker 
232*6777b538SAndroid Build Coastguard Worker   PBYTE exports = reinterpret_cast<PBYTE>(
233*6777b538SAndroid Build Coastguard Worker       GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT));
234*6777b538SAndroid Build Coastguard Worker   DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT);
235*6777b538SAndroid Build Coastguard Worker   if (!exports || !size)
236*6777b538SAndroid Build Coastguard Worker     return nullptr;
237*6777b538SAndroid Build Coastguard Worker 
238*6777b538SAndroid Build Coastguard Worker   // Check for forwarded exports as a special case.
239*6777b538SAndroid Build Coastguard Worker   if (exports <= function && exports + size > function)
240*6777b538SAndroid Build Coastguard Worker     return reinterpret_cast<FARPROC>(-1);
241*6777b538SAndroid Build Coastguard Worker 
242*6777b538SAndroid Build Coastguard Worker   return reinterpret_cast<FARPROC>(function);
243*6777b538SAndroid Build Coastguard Worker }
244*6777b538SAndroid Build Coastguard Worker 
GetProcOrdinal(LPCSTR function_name,WORD * ordinal) const245*6777b538SAndroid Build Coastguard Worker bool PEImage::GetProcOrdinal(LPCSTR function_name, WORD* ordinal) const {
246*6777b538SAndroid Build Coastguard Worker   if (nullptr == ordinal)
247*6777b538SAndroid Build Coastguard Worker     return false;
248*6777b538SAndroid Build Coastguard Worker 
249*6777b538SAndroid Build Coastguard Worker   PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory();
250*6777b538SAndroid Build Coastguard Worker 
251*6777b538SAndroid Build Coastguard Worker   if (nullptr == exports)
252*6777b538SAndroid Build Coastguard Worker     return false;
253*6777b538SAndroid Build Coastguard Worker 
254*6777b538SAndroid Build Coastguard Worker   if (IsOrdinal(function_name)) {
255*6777b538SAndroid Build Coastguard Worker     *ordinal = ToOrdinal(function_name);
256*6777b538SAndroid Build Coastguard Worker   } else {
257*6777b538SAndroid Build Coastguard Worker     PDWORD names = reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfNames));
258*6777b538SAndroid Build Coastguard Worker     PDWORD lower = names;
259*6777b538SAndroid Build Coastguard Worker     PDWORD upper = names + exports->NumberOfNames;
260*6777b538SAndroid Build Coastguard Worker     int cmp = -1;
261*6777b538SAndroid Build Coastguard Worker 
262*6777b538SAndroid Build Coastguard Worker     // Binary Search for the name.
263*6777b538SAndroid Build Coastguard Worker     while (lower != upper) {
264*6777b538SAndroid Build Coastguard Worker       PDWORD middle = lower + (upper - lower) / 2;
265*6777b538SAndroid Build Coastguard Worker       LPCSTR name = reinterpret_cast<LPCSTR>(RVAToAddr(*middle));
266*6777b538SAndroid Build Coastguard Worker 
267*6777b538SAndroid Build Coastguard Worker       // This may be called by sandbox before MSVCRT dll loads, so can't use
268*6777b538SAndroid Build Coastguard Worker       // CRT function here.
269*6777b538SAndroid Build Coastguard Worker       cmp = StrCmpByByte(function_name, name);
270*6777b538SAndroid Build Coastguard Worker 
271*6777b538SAndroid Build Coastguard Worker       if (cmp == 0) {
272*6777b538SAndroid Build Coastguard Worker         lower = middle;
273*6777b538SAndroid Build Coastguard Worker         break;
274*6777b538SAndroid Build Coastguard Worker       }
275*6777b538SAndroid Build Coastguard Worker 
276*6777b538SAndroid Build Coastguard Worker       if (cmp > 0)
277*6777b538SAndroid Build Coastguard Worker         lower = middle + 1;
278*6777b538SAndroid Build Coastguard Worker       else
279*6777b538SAndroid Build Coastguard Worker         upper = middle;
280*6777b538SAndroid Build Coastguard Worker     }
281*6777b538SAndroid Build Coastguard Worker 
282*6777b538SAndroid Build Coastguard Worker     if (cmp != 0)
283*6777b538SAndroid Build Coastguard Worker       return false;
284*6777b538SAndroid Build Coastguard Worker 
285*6777b538SAndroid Build Coastguard Worker     PWORD ordinals =
286*6777b538SAndroid Build Coastguard Worker         reinterpret_cast<PWORD>(RVAToAddr(exports->AddressOfNameOrdinals));
287*6777b538SAndroid Build Coastguard Worker 
288*6777b538SAndroid Build Coastguard Worker     *ordinal = ordinals[lower - names] + static_cast<WORD>(exports->Base);
289*6777b538SAndroid Build Coastguard Worker   }
290*6777b538SAndroid Build Coastguard Worker 
291*6777b538SAndroid Build Coastguard Worker   return true;
292*6777b538SAndroid Build Coastguard Worker }
293*6777b538SAndroid Build Coastguard Worker 
EnumSections(EnumSectionsFunction callback,PVOID cookie) const294*6777b538SAndroid Build Coastguard Worker bool PEImage::EnumSections(EnumSectionsFunction callback, PVOID cookie) const {
295*6777b538SAndroid Build Coastguard Worker   PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
296*6777b538SAndroid Build Coastguard Worker   UINT num_sections = nt_headers->FileHeader.NumberOfSections;
297*6777b538SAndroid Build Coastguard Worker   PIMAGE_SECTION_HEADER section = GetSectionHeader(0);
298*6777b538SAndroid Build Coastguard Worker 
299*6777b538SAndroid Build Coastguard Worker   for (WORD i = 0; i < num_sections; i++, section++) {
300*6777b538SAndroid Build Coastguard Worker     PVOID section_start = RVAToAddr(section->VirtualAddress);
301*6777b538SAndroid Build Coastguard Worker     DWORD size = section->Misc.VirtualSize;
302*6777b538SAndroid Build Coastguard Worker 
303*6777b538SAndroid Build Coastguard Worker     if (!callback(*this, section, section_start, size, cookie))
304*6777b538SAndroid Build Coastguard Worker       return false;
305*6777b538SAndroid Build Coastguard Worker   }
306*6777b538SAndroid Build Coastguard Worker 
307*6777b538SAndroid Build Coastguard Worker   return true;
308*6777b538SAndroid Build Coastguard Worker }
309*6777b538SAndroid Build Coastguard Worker 
EnumExports(EnumExportsFunction callback,PVOID cookie) const310*6777b538SAndroid Build Coastguard Worker bool PEImage::EnumExports(EnumExportsFunction callback, PVOID cookie) const {
311*6777b538SAndroid Build Coastguard Worker   PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT);
312*6777b538SAndroid Build Coastguard Worker   DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT);
313*6777b538SAndroid Build Coastguard Worker 
314*6777b538SAndroid Build Coastguard Worker   // Check if there are any exports at all.
315*6777b538SAndroid Build Coastguard Worker   if (!directory || !size)
316*6777b538SAndroid Build Coastguard Worker     return true;
317*6777b538SAndroid Build Coastguard Worker 
318*6777b538SAndroid Build Coastguard Worker   PIMAGE_EXPORT_DIRECTORY exports =
319*6777b538SAndroid Build Coastguard Worker       reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(directory);
320*6777b538SAndroid Build Coastguard Worker   UINT ordinal_base = exports->Base;
321*6777b538SAndroid Build Coastguard Worker   UINT num_funcs = exports->NumberOfFunctions;
322*6777b538SAndroid Build Coastguard Worker   UINT num_names = exports->NumberOfNames;
323*6777b538SAndroid Build Coastguard Worker   PDWORD functions =
324*6777b538SAndroid Build Coastguard Worker       reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfFunctions));
325*6777b538SAndroid Build Coastguard Worker   PDWORD names = reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfNames));
326*6777b538SAndroid Build Coastguard Worker   PWORD ordinals =
327*6777b538SAndroid Build Coastguard Worker       reinterpret_cast<PWORD>(RVAToAddr(exports->AddressOfNameOrdinals));
328*6777b538SAndroid Build Coastguard Worker 
329*6777b538SAndroid Build Coastguard Worker   for (UINT count = 0; count < num_funcs; count++) {
330*6777b538SAndroid Build Coastguard Worker     PVOID func = RVAToAddr(functions[count]);
331*6777b538SAndroid Build Coastguard Worker     if (nullptr == func)
332*6777b538SAndroid Build Coastguard Worker       continue;
333*6777b538SAndroid Build Coastguard Worker 
334*6777b538SAndroid Build Coastguard Worker     // Check for a name.
335*6777b538SAndroid Build Coastguard Worker     LPCSTR name = nullptr;
336*6777b538SAndroid Build Coastguard Worker     UINT hint;
337*6777b538SAndroid Build Coastguard Worker     for (hint = 0; hint < num_names; hint++) {
338*6777b538SAndroid Build Coastguard Worker       if (ordinals[hint] == count) {
339*6777b538SAndroid Build Coastguard Worker         name = reinterpret_cast<LPCSTR>(RVAToAddr(names[hint]));
340*6777b538SAndroid Build Coastguard Worker         break;
341*6777b538SAndroid Build Coastguard Worker       }
342*6777b538SAndroid Build Coastguard Worker     }
343*6777b538SAndroid Build Coastguard Worker 
344*6777b538SAndroid Build Coastguard Worker     if (name == nullptr)
345*6777b538SAndroid Build Coastguard Worker       hint = 0;
346*6777b538SAndroid Build Coastguard Worker 
347*6777b538SAndroid Build Coastguard Worker     // Check for forwarded exports.
348*6777b538SAndroid Build Coastguard Worker     LPCSTR forward = nullptr;
349*6777b538SAndroid Build Coastguard Worker     if (reinterpret_cast<char*>(func) >= reinterpret_cast<char*>(directory) &&
350*6777b538SAndroid Build Coastguard Worker         reinterpret_cast<char*>(func) <=
351*6777b538SAndroid Build Coastguard Worker             reinterpret_cast<char*>(directory) + size) {
352*6777b538SAndroid Build Coastguard Worker       forward = reinterpret_cast<LPCSTR>(func);
353*6777b538SAndroid Build Coastguard Worker       func = nullptr;
354*6777b538SAndroid Build Coastguard Worker     }
355*6777b538SAndroid Build Coastguard Worker 
356*6777b538SAndroid Build Coastguard Worker     if (!callback(*this, ordinal_base + count, hint, name, func, forward,
357*6777b538SAndroid Build Coastguard Worker                   cookie))
358*6777b538SAndroid Build Coastguard Worker       return false;
359*6777b538SAndroid Build Coastguard Worker   }
360*6777b538SAndroid Build Coastguard Worker 
361*6777b538SAndroid Build Coastguard Worker   return true;
362*6777b538SAndroid Build Coastguard Worker }
363*6777b538SAndroid Build Coastguard Worker 
EnumRelocs(EnumRelocsFunction callback,PVOID cookie) const364*6777b538SAndroid Build Coastguard Worker bool PEImage::EnumRelocs(EnumRelocsFunction callback, PVOID cookie) const {
365*6777b538SAndroid Build Coastguard Worker   PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_BASERELOC);
366*6777b538SAndroid Build Coastguard Worker   DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_BASERELOC);
367*6777b538SAndroid Build Coastguard Worker 
368*6777b538SAndroid Build Coastguard Worker   if (!directory || !size)
369*6777b538SAndroid Build Coastguard Worker     return true;
370*6777b538SAndroid Build Coastguard Worker 
371*6777b538SAndroid Build Coastguard Worker   PIMAGE_BASE_RELOCATION base =
372*6777b538SAndroid Build Coastguard Worker       reinterpret_cast<PIMAGE_BASE_RELOCATION>(directory);
373*6777b538SAndroid Build Coastguard Worker   while (size >= sizeof(IMAGE_BASE_RELOCATION) && base->SizeOfBlock &&
374*6777b538SAndroid Build Coastguard Worker          size >= base->SizeOfBlock) {
375*6777b538SAndroid Build Coastguard Worker     PWORD reloc = reinterpret_cast<PWORD>(base + 1);
376*6777b538SAndroid Build Coastguard Worker     UINT num_relocs =
377*6777b538SAndroid Build Coastguard Worker         (base->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
378*6777b538SAndroid Build Coastguard Worker 
379*6777b538SAndroid Build Coastguard Worker     for (UINT i = 0; i < num_relocs; i++, reloc++) {
380*6777b538SAndroid Build Coastguard Worker       WORD type = *reloc >> 12;
381*6777b538SAndroid Build Coastguard Worker       PVOID address = RVAToAddr(base->VirtualAddress + (*reloc & 0x0FFF));
382*6777b538SAndroid Build Coastguard Worker 
383*6777b538SAndroid Build Coastguard Worker       if (!callback(*this, type, address, cookie))
384*6777b538SAndroid Build Coastguard Worker         return false;
385*6777b538SAndroid Build Coastguard Worker     }
386*6777b538SAndroid Build Coastguard Worker 
387*6777b538SAndroid Build Coastguard Worker     size -= base->SizeOfBlock;
388*6777b538SAndroid Build Coastguard Worker     base = reinterpret_cast<PIMAGE_BASE_RELOCATION>(
389*6777b538SAndroid Build Coastguard Worker         reinterpret_cast<char*>(base) + base->SizeOfBlock);
390*6777b538SAndroid Build Coastguard Worker   }
391*6777b538SAndroid Build Coastguard Worker 
392*6777b538SAndroid Build Coastguard Worker   return true;
393*6777b538SAndroid Build Coastguard Worker }
394*6777b538SAndroid Build Coastguard Worker 
EnumImportChunks(EnumImportChunksFunction callback,PVOID cookie,LPCSTR target_module_name) const395*6777b538SAndroid Build Coastguard Worker bool PEImage::EnumImportChunks(EnumImportChunksFunction callback,
396*6777b538SAndroid Build Coastguard Worker                                PVOID cookie,
397*6777b538SAndroid Build Coastguard Worker                                LPCSTR target_module_name) const {
398*6777b538SAndroid Build Coastguard Worker   DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_IMPORT);
399*6777b538SAndroid Build Coastguard Worker   PIMAGE_IMPORT_DESCRIPTOR import = GetFirstImportChunk();
400*6777b538SAndroid Build Coastguard Worker 
401*6777b538SAndroid Build Coastguard Worker   if (import == nullptr || size < sizeof(IMAGE_IMPORT_DESCRIPTOR))
402*6777b538SAndroid Build Coastguard Worker     return true;
403*6777b538SAndroid Build Coastguard Worker 
404*6777b538SAndroid Build Coastguard Worker   for (; import->FirstThunk; import++) {
405*6777b538SAndroid Build Coastguard Worker     LPCSTR module_name = reinterpret_cast<LPCSTR>(RVAToAddr(import->Name));
406*6777b538SAndroid Build Coastguard Worker     PIMAGE_THUNK_DATA name_table = reinterpret_cast<PIMAGE_THUNK_DATA>(
407*6777b538SAndroid Build Coastguard Worker         RVAToAddr(import->OriginalFirstThunk));
408*6777b538SAndroid Build Coastguard Worker     PIMAGE_THUNK_DATA iat =
409*6777b538SAndroid Build Coastguard Worker         reinterpret_cast<PIMAGE_THUNK_DATA>(RVAToAddr(import->FirstThunk));
410*6777b538SAndroid Build Coastguard Worker 
411*6777b538SAndroid Build Coastguard Worker     if (target_module_name == nullptr ||
412*6777b538SAndroid Build Coastguard Worker         (lstrcmpiA(module_name, target_module_name) == 0)) {
413*6777b538SAndroid Build Coastguard Worker       if (!callback(*this, module_name, name_table, iat, cookie))
414*6777b538SAndroid Build Coastguard Worker         return false;
415*6777b538SAndroid Build Coastguard Worker     }
416*6777b538SAndroid Build Coastguard Worker   }
417*6777b538SAndroid Build Coastguard Worker 
418*6777b538SAndroid Build Coastguard Worker   return true;
419*6777b538SAndroid Build Coastguard Worker }
420*6777b538SAndroid Build Coastguard Worker 
EnumOneImportChunk(EnumImportsFunction callback,LPCSTR module_name,PIMAGE_THUNK_DATA name_table,PIMAGE_THUNK_DATA iat,PVOID cookie) const421*6777b538SAndroid Build Coastguard Worker bool PEImage::EnumOneImportChunk(EnumImportsFunction callback,
422*6777b538SAndroid Build Coastguard Worker                                  LPCSTR module_name,
423*6777b538SAndroid Build Coastguard Worker                                  PIMAGE_THUNK_DATA name_table,
424*6777b538SAndroid Build Coastguard Worker                                  PIMAGE_THUNK_DATA iat,
425*6777b538SAndroid Build Coastguard Worker                                  PVOID cookie) const {
426*6777b538SAndroid Build Coastguard Worker   if (nullptr == name_table)
427*6777b538SAndroid Build Coastguard Worker     return false;
428*6777b538SAndroid Build Coastguard Worker 
429*6777b538SAndroid Build Coastguard Worker   for (; name_table && name_table->u1.Ordinal; name_table++, iat++) {
430*6777b538SAndroid Build Coastguard Worker     LPCSTR name = nullptr;
431*6777b538SAndroid Build Coastguard Worker     WORD ordinal = 0;
432*6777b538SAndroid Build Coastguard Worker     WORD hint = 0;
433*6777b538SAndroid Build Coastguard Worker 
434*6777b538SAndroid Build Coastguard Worker     if (IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) {
435*6777b538SAndroid Build Coastguard Worker       ordinal = static_cast<WORD>(IMAGE_ORDINAL32(name_table->u1.Ordinal));
436*6777b538SAndroid Build Coastguard Worker     } else {
437*6777b538SAndroid Build Coastguard Worker       PIMAGE_IMPORT_BY_NAME import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(
438*6777b538SAndroid Build Coastguard Worker           RVAToAddr(name_table->u1.ForwarderString));
439*6777b538SAndroid Build Coastguard Worker 
440*6777b538SAndroid Build Coastguard Worker       hint = import->Hint;
441*6777b538SAndroid Build Coastguard Worker       name = reinterpret_cast<LPCSTR>(&import->Name);
442*6777b538SAndroid Build Coastguard Worker     }
443*6777b538SAndroid Build Coastguard Worker 
444*6777b538SAndroid Build Coastguard Worker     if (!callback(*this, module_name, ordinal, name, hint, iat, cookie))
445*6777b538SAndroid Build Coastguard Worker       return false;
446*6777b538SAndroid Build Coastguard Worker   }
447*6777b538SAndroid Build Coastguard Worker 
448*6777b538SAndroid Build Coastguard Worker   return true;
449*6777b538SAndroid Build Coastguard Worker }
450*6777b538SAndroid Build Coastguard Worker 
EnumAllImports(EnumImportsFunction callback,PVOID cookie,LPCSTR target_module_name) const451*6777b538SAndroid Build Coastguard Worker bool PEImage::EnumAllImports(EnumImportsFunction callback,
452*6777b538SAndroid Build Coastguard Worker                              PVOID cookie,
453*6777b538SAndroid Build Coastguard Worker                              LPCSTR target_module_name) const {
454*6777b538SAndroid Build Coastguard Worker   EnumAllImportsStorage temp = {callback, cookie};
455*6777b538SAndroid Build Coastguard Worker   return EnumImportChunks(ProcessImportChunk, &temp, target_module_name);
456*6777b538SAndroid Build Coastguard Worker }
457*6777b538SAndroid Build Coastguard Worker 
EnumDelayImportChunks(EnumDelayImportChunksFunction callback,PVOID cookie,LPCSTR target_module_name) const458*6777b538SAndroid Build Coastguard Worker bool PEImage::EnumDelayImportChunks(EnumDelayImportChunksFunction callback,
459*6777b538SAndroid Build Coastguard Worker                                     PVOID cookie,
460*6777b538SAndroid Build Coastguard Worker                                     LPCSTR target_module_name) const {
461*6777b538SAndroid Build Coastguard Worker   PVOID directory =
462*6777b538SAndroid Build Coastguard Worker       GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
463*6777b538SAndroid Build Coastguard Worker   DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
464*6777b538SAndroid Build Coastguard Worker 
465*6777b538SAndroid Build Coastguard Worker   if (!directory || !size)
466*6777b538SAndroid Build Coastguard Worker     return true;
467*6777b538SAndroid Build Coastguard Worker 
468*6777b538SAndroid Build Coastguard Worker   PImgDelayDescr delay_descriptor = reinterpret_cast<PImgDelayDescr>(directory);
469*6777b538SAndroid Build Coastguard Worker   for (; delay_descriptor->rvaHmod; delay_descriptor++) {
470*6777b538SAndroid Build Coastguard Worker     PIMAGE_THUNK_DATA name_table;
471*6777b538SAndroid Build Coastguard Worker     PIMAGE_THUNK_DATA iat;
472*6777b538SAndroid Build Coastguard Worker     LPCSTR module_name;
473*6777b538SAndroid Build Coastguard Worker 
474*6777b538SAndroid Build Coastguard Worker     // check if VC7-style imports, using RVAs instead of
475*6777b538SAndroid Build Coastguard Worker     // VC6-style addresses.
476*6777b538SAndroid Build Coastguard Worker     bool rvas = (delay_descriptor->grAttrs & dlattrRva) != 0;
477*6777b538SAndroid Build Coastguard Worker 
478*6777b538SAndroid Build Coastguard Worker     if (rvas) {
479*6777b538SAndroid Build Coastguard Worker       module_name =
480*6777b538SAndroid Build Coastguard Worker           reinterpret_cast<LPCSTR>(RVAToAddr(delay_descriptor->rvaDLLName));
481*6777b538SAndroid Build Coastguard Worker       name_table = reinterpret_cast<PIMAGE_THUNK_DATA>(
482*6777b538SAndroid Build Coastguard Worker           RVAToAddr(delay_descriptor->rvaINT));
483*6777b538SAndroid Build Coastguard Worker       iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
484*6777b538SAndroid Build Coastguard Worker           RVAToAddr(delay_descriptor->rvaIAT));
485*6777b538SAndroid Build Coastguard Worker     } else {
486*6777b538SAndroid Build Coastguard Worker       // Values in IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT are 32-bit, even on 64-bit
487*6777b538SAndroid Build Coastguard Worker       // platforms. See section 4.8 of PECOFF image spec rev 8.3.
488*6777b538SAndroid Build Coastguard Worker       module_name = reinterpret_cast<LPCSTR>(
489*6777b538SAndroid Build Coastguard Worker           static_cast<uintptr_t>(delay_descriptor->rvaDLLName));
490*6777b538SAndroid Build Coastguard Worker       name_table = reinterpret_cast<PIMAGE_THUNK_DATA>(
491*6777b538SAndroid Build Coastguard Worker           static_cast<uintptr_t>(delay_descriptor->rvaINT));
492*6777b538SAndroid Build Coastguard Worker       iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
493*6777b538SAndroid Build Coastguard Worker           static_cast<uintptr_t>(delay_descriptor->rvaIAT));
494*6777b538SAndroid Build Coastguard Worker     }
495*6777b538SAndroid Build Coastguard Worker 
496*6777b538SAndroid Build Coastguard Worker     if (target_module_name == nullptr ||
497*6777b538SAndroid Build Coastguard Worker         (lstrcmpiA(module_name, target_module_name) == 0)) {
498*6777b538SAndroid Build Coastguard Worker       if (target_module_name) {
499*6777b538SAndroid Build Coastguard Worker         // Ensure all imports are properly loaded for the target module so that
500*6777b538SAndroid Build Coastguard Worker         // the callback is operating on a fully-realized set of imports.
501*6777b538SAndroid Build Coastguard Worker         // This call only loads the imports for the module where this code is
502*6777b538SAndroid Build Coastguard Worker         // executing, so it is only helpful or meaningful to do this if the
503*6777b538SAndroid Build Coastguard Worker         // current module is the module whose IAT we are enumerating.
504*6777b538SAndroid Build Coastguard Worker         // Use the module_name as retrieved from the IAT because this method
505*6777b538SAndroid Build Coastguard Worker         // is case sensitive.
506*6777b538SAndroid Build Coastguard Worker         if (module_ == CURRENT_MODULE() && !LDR_IS_RESOURCE(module_)) {
507*6777b538SAndroid Build Coastguard Worker           static base::NoDestructor<std::set<std::string>> loaded_dlls;
508*6777b538SAndroid Build Coastguard Worker           // pair.second is true if this is a new element
509*6777b538SAndroid Build Coastguard Worker           if (loaded_dlls.get()->emplace(module_name).second)
510*6777b538SAndroid Build Coastguard Worker             ::__HrLoadAllImportsForDll(module_name);
511*6777b538SAndroid Build Coastguard Worker         }
512*6777b538SAndroid Build Coastguard Worker       }
513*6777b538SAndroid Build Coastguard Worker 
514*6777b538SAndroid Build Coastguard Worker       if (!callback(*this, delay_descriptor, module_name, name_table, iat,
515*6777b538SAndroid Build Coastguard Worker                     cookie))
516*6777b538SAndroid Build Coastguard Worker         return false;
517*6777b538SAndroid Build Coastguard Worker     }
518*6777b538SAndroid Build Coastguard Worker   }
519*6777b538SAndroid Build Coastguard Worker 
520*6777b538SAndroid Build Coastguard Worker   return true;
521*6777b538SAndroid Build Coastguard Worker }
522*6777b538SAndroid Build Coastguard Worker 
EnumOneDelayImportChunk(EnumImportsFunction callback,PImgDelayDescr delay_descriptor,LPCSTR module_name,PIMAGE_THUNK_DATA name_table,PIMAGE_THUNK_DATA iat,PVOID cookie) const523*6777b538SAndroid Build Coastguard Worker bool PEImage::EnumOneDelayImportChunk(EnumImportsFunction callback,
524*6777b538SAndroid Build Coastguard Worker                                       PImgDelayDescr delay_descriptor,
525*6777b538SAndroid Build Coastguard Worker                                       LPCSTR module_name,
526*6777b538SAndroid Build Coastguard Worker                                       PIMAGE_THUNK_DATA name_table,
527*6777b538SAndroid Build Coastguard Worker                                       PIMAGE_THUNK_DATA iat,
528*6777b538SAndroid Build Coastguard Worker                                       PVOID cookie) const {
529*6777b538SAndroid Build Coastguard Worker   for (; name_table->u1.Ordinal; name_table++, iat++) {
530*6777b538SAndroid Build Coastguard Worker     LPCSTR name = nullptr;
531*6777b538SAndroid Build Coastguard Worker     WORD ordinal = 0;
532*6777b538SAndroid Build Coastguard Worker     WORD hint = 0;
533*6777b538SAndroid Build Coastguard Worker 
534*6777b538SAndroid Build Coastguard Worker     if (IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) {
535*6777b538SAndroid Build Coastguard Worker       ordinal = static_cast<WORD>(IMAGE_ORDINAL32(name_table->u1.Ordinal));
536*6777b538SAndroid Build Coastguard Worker     } else {
537*6777b538SAndroid Build Coastguard Worker       PIMAGE_IMPORT_BY_NAME import;
538*6777b538SAndroid Build Coastguard Worker       bool rvas = (delay_descriptor->grAttrs & dlattrRva) != 0;
539*6777b538SAndroid Build Coastguard Worker 
540*6777b538SAndroid Build Coastguard Worker       if (rvas) {
541*6777b538SAndroid Build Coastguard Worker         import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(
542*6777b538SAndroid Build Coastguard Worker             RVAToAddr(name_table->u1.ForwarderString));
543*6777b538SAndroid Build Coastguard Worker       } else {
544*6777b538SAndroid Build Coastguard Worker         import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(
545*6777b538SAndroid Build Coastguard Worker             name_table->u1.ForwarderString);
546*6777b538SAndroid Build Coastguard Worker       }
547*6777b538SAndroid Build Coastguard Worker 
548*6777b538SAndroid Build Coastguard Worker       hint = import->Hint;
549*6777b538SAndroid Build Coastguard Worker       name = reinterpret_cast<LPCSTR>(&import->Name);
550*6777b538SAndroid Build Coastguard Worker     }
551*6777b538SAndroid Build Coastguard Worker 
552*6777b538SAndroid Build Coastguard Worker     if (!callback(*this, module_name, ordinal, name, hint, iat, cookie))
553*6777b538SAndroid Build Coastguard Worker       return false;
554*6777b538SAndroid Build Coastguard Worker   }
555*6777b538SAndroid Build Coastguard Worker 
556*6777b538SAndroid Build Coastguard Worker   return true;
557*6777b538SAndroid Build Coastguard Worker }
558*6777b538SAndroid Build Coastguard Worker 
EnumAllDelayImports(EnumImportsFunction callback,PVOID cookie,LPCSTR target_module_name) const559*6777b538SAndroid Build Coastguard Worker bool PEImage::EnumAllDelayImports(EnumImportsFunction callback,
560*6777b538SAndroid Build Coastguard Worker                                   PVOID cookie,
561*6777b538SAndroid Build Coastguard Worker                                   LPCSTR target_module_name) const {
562*6777b538SAndroid Build Coastguard Worker   EnumAllImportsStorage temp = {callback, cookie};
563*6777b538SAndroid Build Coastguard Worker   return EnumDelayImportChunks(ProcessDelayImportChunk, &temp,
564*6777b538SAndroid Build Coastguard Worker                                target_module_name);
565*6777b538SAndroid Build Coastguard Worker }
566*6777b538SAndroid Build Coastguard Worker 
VerifyMagic() const567*6777b538SAndroid Build Coastguard Worker bool PEImage::VerifyMagic() const {
568*6777b538SAndroid Build Coastguard Worker   PIMAGE_DOS_HEADER dos_header = GetDosHeader();
569*6777b538SAndroid Build Coastguard Worker 
570*6777b538SAndroid Build Coastguard Worker   if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
571*6777b538SAndroid Build Coastguard Worker     return false;
572*6777b538SAndroid Build Coastguard Worker 
573*6777b538SAndroid Build Coastguard Worker   PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
574*6777b538SAndroid Build Coastguard Worker 
575*6777b538SAndroid Build Coastguard Worker   if (nt_headers->Signature != IMAGE_NT_SIGNATURE)
576*6777b538SAndroid Build Coastguard Worker     return false;
577*6777b538SAndroid Build Coastguard Worker 
578*6777b538SAndroid Build Coastguard Worker   if (nt_headers->FileHeader.SizeOfOptionalHeader !=
579*6777b538SAndroid Build Coastguard Worker       sizeof(IMAGE_OPTIONAL_HEADER))
580*6777b538SAndroid Build Coastguard Worker     return false;
581*6777b538SAndroid Build Coastguard Worker 
582*6777b538SAndroid Build Coastguard Worker   if (nt_headers->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
583*6777b538SAndroid Build Coastguard Worker     return false;
584*6777b538SAndroid Build Coastguard Worker 
585*6777b538SAndroid Build Coastguard Worker   return true;
586*6777b538SAndroid Build Coastguard Worker }
587*6777b538SAndroid Build Coastguard Worker 
ImageRVAToOnDiskOffset(uintptr_t rva,DWORD * on_disk_offset) const588*6777b538SAndroid Build Coastguard Worker bool PEImage::ImageRVAToOnDiskOffset(uintptr_t rva,
589*6777b538SAndroid Build Coastguard Worker                                      DWORD* on_disk_offset) const {
590*6777b538SAndroid Build Coastguard Worker   LPVOID address = RVAToAddr(rva);
591*6777b538SAndroid Build Coastguard Worker   return ImageAddrToOnDiskOffset(address, on_disk_offset);
592*6777b538SAndroid Build Coastguard Worker }
593*6777b538SAndroid Build Coastguard Worker 
ImageAddrToOnDiskOffset(LPVOID address,DWORD * on_disk_offset) const594*6777b538SAndroid Build Coastguard Worker bool PEImage::ImageAddrToOnDiskOffset(LPVOID address,
595*6777b538SAndroid Build Coastguard Worker                                       DWORD* on_disk_offset) const {
596*6777b538SAndroid Build Coastguard Worker   if (nullptr == address)
597*6777b538SAndroid Build Coastguard Worker     return false;
598*6777b538SAndroid Build Coastguard Worker 
599*6777b538SAndroid Build Coastguard Worker   // Get the section that this address belongs to.
600*6777b538SAndroid Build Coastguard Worker   PIMAGE_SECTION_HEADER section_header = GetImageSectionFromAddr(address);
601*6777b538SAndroid Build Coastguard Worker   if (nullptr == section_header)
602*6777b538SAndroid Build Coastguard Worker     return false;
603*6777b538SAndroid Build Coastguard Worker 
604*6777b538SAndroid Build Coastguard Worker   // Don't follow the virtual RVAToAddr, use the one on the base.
605*6777b538SAndroid Build Coastguard Worker   DWORD offset_within_section =
606*6777b538SAndroid Build Coastguard Worker       static_cast<DWORD>(reinterpret_cast<uintptr_t>(address)) -
607*6777b538SAndroid Build Coastguard Worker       static_cast<DWORD>(reinterpret_cast<uintptr_t>(
608*6777b538SAndroid Build Coastguard Worker           PEImage::RVAToAddr(section_header->VirtualAddress)));
609*6777b538SAndroid Build Coastguard Worker 
610*6777b538SAndroid Build Coastguard Worker   *on_disk_offset = section_header->PointerToRawData + offset_within_section;
611*6777b538SAndroid Build Coastguard Worker   return true;
612*6777b538SAndroid Build Coastguard Worker }
613*6777b538SAndroid Build Coastguard Worker 
RVAToAddr(uintptr_t rva) const614*6777b538SAndroid Build Coastguard Worker PVOID PEImage::RVAToAddr(uintptr_t rva) const {
615*6777b538SAndroid Build Coastguard Worker   if (rva == 0)
616*6777b538SAndroid Build Coastguard Worker     return nullptr;
617*6777b538SAndroid Build Coastguard Worker 
618*6777b538SAndroid Build Coastguard Worker   return reinterpret_cast<char*>(module_) + rva;
619*6777b538SAndroid Build Coastguard Worker }
620*6777b538SAndroid Build Coastguard Worker 
GetDataDirectory(UINT directory) const621*6777b538SAndroid Build Coastguard Worker const IMAGE_DATA_DIRECTORY* PEImage::GetDataDirectory(UINT directory) const {
622*6777b538SAndroid Build Coastguard Worker   PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
623*6777b538SAndroid Build Coastguard Worker 
624*6777b538SAndroid Build Coastguard Worker   // Does the image report that it includes this directory entry?
625*6777b538SAndroid Build Coastguard Worker   if (directory >= nt_headers->OptionalHeader.NumberOfRvaAndSizes)
626*6777b538SAndroid Build Coastguard Worker     return nullptr;
627*6777b538SAndroid Build Coastguard Worker 
628*6777b538SAndroid Build Coastguard Worker   // Is there space for this directory entry in the optional header?
629*6777b538SAndroid Build Coastguard Worker   if (nt_headers->FileHeader.SizeOfOptionalHeader <
630*6777b538SAndroid Build Coastguard Worker       (offsetof(IMAGE_OPTIONAL_HEADER, DataDirectory) +
631*6777b538SAndroid Build Coastguard Worker        (directory + 1) * sizeof(IMAGE_DATA_DIRECTORY))) {
632*6777b538SAndroid Build Coastguard Worker     return nullptr;
633*6777b538SAndroid Build Coastguard Worker   }
634*6777b538SAndroid Build Coastguard Worker 
635*6777b538SAndroid Build Coastguard Worker   return &nt_headers->OptionalHeader.DataDirectory[directory];
636*6777b538SAndroid Build Coastguard Worker }
637*6777b538SAndroid Build Coastguard Worker 
RVAToAddr(uintptr_t rva) const638*6777b538SAndroid Build Coastguard Worker PVOID PEImageAsData::RVAToAddr(uintptr_t rva) const {
639*6777b538SAndroid Build Coastguard Worker   if (rva == 0)
640*6777b538SAndroid Build Coastguard Worker     return nullptr;
641*6777b538SAndroid Build Coastguard Worker 
642*6777b538SAndroid Build Coastguard Worker   PVOID in_memory = PEImage::RVAToAddr(rva);
643*6777b538SAndroid Build Coastguard Worker   DWORD disk_offset;
644*6777b538SAndroid Build Coastguard Worker 
645*6777b538SAndroid Build Coastguard Worker   if (!ImageAddrToOnDiskOffset(in_memory, &disk_offset))
646*6777b538SAndroid Build Coastguard Worker     return nullptr;
647*6777b538SAndroid Build Coastguard Worker 
648*6777b538SAndroid Build Coastguard Worker   return PEImage::RVAToAddr(disk_offset);
649*6777b538SAndroid Build Coastguard Worker }
650*6777b538SAndroid Build Coastguard Worker 
651*6777b538SAndroid Build Coastguard Worker }  // namespace win
652*6777b538SAndroid Build Coastguard Worker }  // namespace base
653