security/sandbox/chromium/base/win/pe_image.cc

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial