OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This file implements PEImage, a generic class to manipulate PE files. | 5 // This file implements PEImage, a generic class to manipulate PE files. |
6 // This file was adapted from GreenBorder's Code. | 6 // This file was adapted from GreenBorder's Code. |
7 | 7 |
8 #include "base/win/pe_image.h" | 8 #include "base/win/pe_image.h" |
9 | 9 |
10 namespace base { | 10 namespace base { |
11 namespace win { | 11 namespace win { |
12 | 12 |
13 // TODO(jschuh): crbug.com/167707 Make sure this code works on 64-bit. | 13 // TODO(jschuh): crbug.com/167707 Make sure this code works on 64-bit. |
14 | 14 |
15 // Structure to perform imports enumerations. | 15 // Structure to perform imports enumerations. |
16 struct EnumAllImportsStorage { | 16 struct EnumAllImportsStorage { |
17 PEImage::EnumImportsFunction callback; | 17 PEImage::EnumImportsFunction callback; |
18 PVOID cookie; | 18 PVOID cookie; |
19 }; | 19 }; |
20 | 20 |
21 namespace { | 21 namespace { |
22 | 22 |
23 // PdbInfo Signature | |
24 const DWORD kPdbInfoSignature = 'SDSR'; | |
25 | |
26 // Compare two strings byte by byte on an unsigned basis. | 23 // Compare two strings byte by byte on an unsigned basis. |
27 // if s1 == s2, return 0 | 24 // if s1 == s2, return 0 |
28 // if s1 < s2, return negative | 25 // if s1 < s2, return negative |
29 // if s1 > s2, return positive | 26 // if s1 > s2, return positive |
30 // Exception if inputs are invalid. | 27 // Exception if inputs are invalid. |
31 int StrCmpByByte(LPCSTR s1, LPCSTR s2) { | 28 int StrCmpByByte(LPCSTR s1, LPCSTR s2) { |
32 while (*s1 != '\0' && *s1 == *s2) { | 29 while (*s1 != '\0' && *s1 == *s2) { |
33 ++s1; | 30 ++s1; |
34 ++s2; | 31 ++s2; |
35 } | 32 } |
36 | 33 |
37 return (*reinterpret_cast<const unsigned char*>(s1) - | 34 return (*reinterpret_cast<const unsigned char*>(s1) - |
38 *reinterpret_cast<const unsigned char*>(s2)); | 35 *reinterpret_cast<const unsigned char*>(s2)); |
39 } | 36 } |
40 | 37 |
41 struct PdbInfo { | |
42 DWORD Signature; | |
43 GUID Guid; | |
44 DWORD Age; | |
45 char PdbFileName[1]; | |
46 }; | |
47 } // namespace | 38 } // namespace |
48 | 39 |
49 // Callback used to enumerate imports. See EnumImportChunksFunction. | 40 // Callback used to enumerate imports. See EnumImportChunksFunction. |
50 bool ProcessImportChunk(const PEImage &image, LPCSTR module, | 41 bool ProcessImportChunk(const PEImage &image, LPCSTR module, |
51 PIMAGE_THUNK_DATA name_table, | 42 PIMAGE_THUNK_DATA name_table, |
52 PIMAGE_THUNK_DATA iat, PVOID cookie) { | 43 PIMAGE_THUNK_DATA iat, PVOID cookie) { |
53 EnumAllImportsStorage &storage = *reinterpret_cast<EnumAllImportsStorage*>( | 44 EnumAllImportsStorage &storage = *reinterpret_cast<EnumAllImportsStorage*>( |
54 cookie); | 45 cookie); |
55 | 46 |
56 return image.EnumOneImportChunk(storage.callback, module, name_table, iat, | 47 return image.EnumOneImportChunk(storage.callback, module, name_table, iat, |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 if (0 == _strnicmp(reinterpret_cast<LPCSTR>(section->Name), section_name, | 135 if (0 == _strnicmp(reinterpret_cast<LPCSTR>(section->Name), section_name, |
145 sizeof(section->Name))) { | 136 sizeof(section->Name))) { |
146 ret = section; | 137 ret = section; |
147 break; | 138 break; |
148 } | 139 } |
149 } | 140 } |
150 | 141 |
151 return ret; | 142 return ret; |
152 } | 143 } |
153 | 144 |
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 { | 145 PDWORD PEImage::GetExportEntry(LPCSTR name) const { |
185 PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory(); | 146 PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory(); |
186 | 147 |
187 if (NULL == exports) | 148 if (NULL == exports) |
188 return NULL; | 149 return NULL; |
189 | 150 |
190 WORD ordinal = 0; | 151 WORD ordinal = 0; |
191 if (!GetProcOrdinal(name, &ordinal)) | 152 if (!GetProcOrdinal(name, &ordinal)) |
192 return NULL; | 153 return NULL; |
193 | 154 |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 DWORD disk_offset; | 557 DWORD disk_offset; |
597 | 558 |
598 if (!ImageAddrToOnDiskOffset(in_memory, &disk_offset)) | 559 if (!ImageAddrToOnDiskOffset(in_memory, &disk_offset)) |
599 return NULL; | 560 return NULL; |
600 | 561 |
601 return PEImage::RVAToAddr(disk_offset); | 562 return PEImage::RVAToAddr(disk_offset); |
602 } | 563 } |
603 | 564 |
604 } // namespace win | 565 } // namespace win |
605 } // namespace base | 566 } // namespace base |
OLD | NEW |