Coverage for /Syzygy/pe/pe_file_impl.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
87.9%2703070.C++source

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  
  15    :  #ifndef SYZYGY_PE_PE_FILE_IMPL_H_
  16    :  #define SYZYGY_PE_PE_FILE_IMPL_H_
  17    :  
  18    :  namespace pe {
  19    :  
  20    :  template <class ImageNtHeaders, DWORD MagicValidation>
  21    :  bool PEFileBase<ImageNtHeaders, MagicValidation>::Init(
  22  E :      const base::FilePath& path) {
  23  E :    if (!PECoffFile::Init(path))
  24  E :      return false;
  25  E :    if (!ReadHeaders())
  26  E :      return false;
  27  E :    if (!ReadSections())
  28  i :      return false;
  29  E :    return true;
  30  E :  }
  31    :  
  32    :  template <class ImageNtHeaders, DWORD MagicValidation>
  33    :  void PEFileBase<ImageNtHeaders, MagicValidation>::GetSignature(
  34  E :      Signature* signature) const {
  35  E :    DCHECK_NE(static_cast<Signature*>(NULL), signature);
  36  E :    DCHECK_NE(static_cast<ImageNtHeaders*>(NULL), nt_headers_);
  37    :  
  38    :    // TODO(chrisha): Make GetSignature return a bool, and update all calling
  39    :    //     sites.
  40  E :    base::FilePath abs_path(base::MakeAbsoluteFilePath(path_));
  41  E :    CHECK(!abs_path.empty());
  42    :  
  43  E :    signature->path = abs_path.value();
  44  E :    signature->base_address =
  45    :        AbsoluteAddress(nt_headers_->OptionalHeader.ImageBase);
  46  E :    signature->module_size = nt_headers_->OptionalHeader.SizeOfImage;
  47  E :    signature->module_time_date_stamp = nt_headers_->FileHeader.TimeDateStamp;
  48  E :    signature->module_checksum = nt_headers_->OptionalHeader.CheckSum;
  49  E :  }
  50    :  
  51    :  template <class ImageNtHeaders, DWORD MagicValidation>
  52    :  bool PEFileBase<ImageNtHeaders, MagicValidation>::DecodeRelocs(
  53  E :      RelocSet* relocs) const {
  54  E :    DCHECK_NE(static_cast<ImageNtHeaders*>(NULL), nt_headers_);
  55  E :    DCHECK_NE(static_cast<RelocSet*>(NULL), relocs);
  56    :  
  57    :    // Walk the relocs.
  58    :    IMAGE_DATA_DIRECTORY dir =
  59    :        nt_headers_->OptionalHeader.DataDirectory[
  60  E :            IMAGE_DIRECTORY_ENTRY_BASERELOC];
  61  E :    RelativeAddress offs(dir.VirtualAddress);
  62  E :    RelativeAddress end(offs + dir.Size);
  63    :  
  64  E :    const IMAGE_BASE_RELOCATION* hdr = NULL;
  65  E :    for (; offs < end; offs += hdr->SizeOfBlock) {
  66    :      // Read the next header.
  67  E :      if (!GetImageData(offs, sizeof(hdr), &hdr)) {
  68  i :        LOG(ERROR) << "Failed to read relocation block header.";
  69  i :        return false;
  70    :      }
  71    :  
  72    :      // Read the entries.
  73  E :      size_t num_relocs = (hdr->SizeOfBlock - sizeof(*hdr)) / sizeof(WORD);
  74  E :      const WORD* reloc_block = NULL;
  75  E :      if (!GetImageData(offs + sizeof(*hdr), sizeof(*reloc_block) * num_relocs,
  76    :                        &reloc_block)) {
  77  i :        LOG(ERROR) << "Failed to read relocation entries.";
  78  i :        return false;
  79    :      }
  80    :  
  81    :      // Walk the entries.
  82  E :      for (size_t i = 0; i < num_relocs; ++i) {
  83  E :        uint8_t type = reloc_block[i] >> 12;
  84  E :        uint16_t offs = reloc_block[i] & 0xFFF;
  85  E :        DCHECK(type == IMAGE_REL_BASED_HIGHLOW ||
  86    :                type == IMAGE_REL_BASED_ABSOLUTE);
  87    :  
  88  E :        if (type == IMAGE_REL_BASED_HIGHLOW) {
  89    :          // Record the entry.
  90  E :          relocs->insert(RelativeAddress(hdr->VirtualAddress) + offs);
  91    :        }
  92  E :      }
  93  E :    }
  94    :  
  95  E :    DCHECK(offs == end);
  96  E :    return true;
  97  E :  }
  98    :  
  99    :  template <class ImageNtHeaders, DWORD MagicValidation>
 100    :  bool PEFileBase<ImageNtHeaders, MagicValidation>::ReadRelocs(
 101  E :      const RelocSet& relocs, RelocMap* reloc_values) const {
 102  E :    RelocSet::const_iterator it(relocs.begin());
 103  E :    for (; it != relocs.end(); ++it) {
 104  E :      const AbsoluteAddress* abs = NULL;
 105  E :      if (!GetImageData(*it, sizeof(*abs), &abs)) {
 106  i :        LOG(ERROR) << "Failed to read reloc at " << it->value() << ".";
 107  i :        return false;
 108    :      }
 109    :  
 110  E :      reloc_values->insert(std::make_pair(*it, *abs));
 111  E :    }
 112    :  
 113  E :    return true;
 114  E :  }
 115    :  
 116    :  template <class ImageNtHeaders, DWORD MagicValidation>
 117    :  bool PEFileBase<ImageNtHeaders, MagicValidation>::DecodeImports(
 118  E :      ImportDllVector* imports) const {
 119  E :    DCHECK_NE(static_cast<ImportDllVector*>(NULL), imports);
 120    :  
 121    :    // Walk the import thunks.
 122    :    IMAGE_DATA_DIRECTORY dir = nt_headers_->OptionalHeader.
 123  E :        DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
 124  E :    RelativeAddress offs(dir.VirtualAddress);
 125  E :    RelativeAddress end(offs + dir.Size);
 126    :  
 127  E :    const IMAGE_IMPORT_DESCRIPTOR* import_desc = NULL;
 128  E :    for (; offs < end; offs += sizeof(*import_desc)) {
 129  E :      if (!GetImageData(offs, sizeof(*import_desc), &import_desc)) {
 130  i :        LOG(ERROR) << "Unable to read import descriptor.";
 131  i :        return false;
 132    :      }
 133    :  
 134  E :      if (import_desc->Characteristics == 0 && import_desc->FirstThunk == 0) {
 135    :        // This is the last chunk, bail the loop.
 136  E :        break;
 137    :      }
 138    :  
 139  E :      std::string dll_name;
 140  E :      if (!ReadImageString(RelativeAddress(import_desc->Name), &dll_name)) {
 141  i :        LOG(ERROR) << "Unable to read import descriptor name.";
 142  i :        return false;
 143    :      }
 144    :  
 145    :      // Iterate the Import Name Table and the Import Address Table
 146    :      // concurrently. They will yield, respectively, the name of the
 147    :      // function and the address of the entry.
 148  E :      RelativeAddress int_offs(import_desc->OriginalFirstThunk);
 149  E :      RelativeAddress iat_offs(import_desc->FirstThunk);
 150    :  
 151  E :      imports->push_back(ImportDll());
 152  E :      ImportDll& dll = imports->back();
 153  E :      dll.name = dll_name;
 154  E :      dll.desc = *import_desc;
 155    :  
 156  E :      while (true) {
 157  E :        IMAGE_THUNK_DATA int_thunk = {};
 158  E :        IMAGE_THUNK_DATA iat_thunk = {};
 159    :  
 160  E :        if (!ReadImage(int_offs, &int_thunk, sizeof(int_thunk)) ||
 161    :            !ReadImage(iat_offs, &iat_thunk, sizeof(iat_thunk))) {
 162  i :          LOG(ERROR) << "Unable to read import name or address table thunk.";
 163  i :          return false;
 164    :        }
 165    :  
 166    :        // Are we at the end of the table?
 167  E :        if (int_thunk.u1.Function == 0) {
 168  E :          DCHECK_EQ(0U, iat_thunk.u1.Function);
 169  E :          break;
 170    :        }
 171    :  
 172  E :        uint16_t hint = 0;
 173  E :        uint16_t ordinal = 0;
 174  E :        std::string function_name;
 175  E :        if (int_thunk.u1.AddressOfData & IMAGE_ORDINAL_FLAG32) {
 176    :          // It's an ordinal.
 177  E :          ordinal = IMAGE_ORDINAL32(int_thunk.u1.Ordinal);
 178  E :        } else {
 179    :          // Read the hint word, followed by the function name.
 180  E :          RelativeAddress import_name(int_thunk.u1.AddressOfData);
 181  E :          if (!ReadImage(import_name, &hint, sizeof(hint)) ||
 182    :              !ReadImageString(import_name + sizeof(hint), &function_name)) {
 183  i :            LOG(ERROR) << "Unable to read import function hint or name.";
 184  i :            return false;
 185    :          }
 186    :        }
 187    :  
 188  E :        dll.functions.push_back(ImportInfo());
 189  E :        ImportInfo& info = dll.functions.back();
 190  E :        info.function = function_name;
 191  E :        info.ordinal = ordinal;
 192  E :        info.hint = hint;
 193    :  
 194  E :        int_offs += sizeof(int_thunk);
 195  E :        iat_offs += sizeof(iat_thunk);
 196  E :      }
 197  E :    }
 198    :  
 199  E :    return true;
 200  E :  }
 201    :  
 202    :  template <class ImageNtHeaders, DWORD MagicValidation>
 203    :  bool PEFileBase<ImageNtHeaders, MagicValidation>::DecodeExports(
 204  E :      ExportInfoVector* exports) const {
 205  E :    DCHECK_NE(static_cast<ExportInfoVector*>(NULL), exports);
 206    :  
 207    :    IMAGE_DATA_DIRECTORY dir = nt_headers_->OptionalHeader.
 208  E :        DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
 209  E :    RelativeAddress addr(dir.VirtualAddress);
 210  E :    RelativeAddress end(addr + dir.Size);
 211    :  
 212  E :    if (addr.value() == 0)
 213  i :      return true;
 214    :  
 215  E :    const IMAGE_EXPORT_DIRECTORY* export_dir = NULL;
 216  E :    if (!GetImageData(addr, sizeof(export_dir), &export_dir)) {
 217  i :      LOG(ERROR) << "Unable to read export directory.";
 218  i :      return false;
 219    :    }
 220    :  
 221  E :    const RelativeAddress* functions = NULL;
 222  E :    if (!GetImageData(RelativeAddress(export_dir->AddressOfFunctions),
 223    :                      sizeof(*functions) * export_dir->NumberOfFunctions,
 224    :                      &functions)) {
 225  i :      LOG(ERROR) << "Unable to read export functions.";
 226  i :      return false;
 227    :    }
 228    :  
 229  E :    const RelativeAddress* names = NULL;
 230  E :    if (!GetImageData(RelativeAddress(export_dir->AddressOfNames),
 231    :                      sizeof(*functions) * export_dir->NumberOfNames,
 232    :                      &names)) {
 233  i :      LOG(ERROR) << "Unable to read export names.";
 234  i :      return false;
 235    :    }
 236    :  
 237  E :    const WORD* name_ordinals = NULL;
 238  E :    if (!GetImageData(RelativeAddress(export_dir->AddressOfNameOrdinals),
 239    :                      sizeof(*functions) * export_dir->NumberOfNames,
 240    :                      &name_ordinals)) {
 241  i :      LOG(ERROR) << "Unable to read name ordinals.";
 242  i :      return false;
 243    :    }
 244    :  
 245  E :    for (uint16_t index = 0; index < export_dir->NumberOfFunctions; ++index) {
 246    :      // Is it a blank entry?
 247  E :      if (functions[index] != RelativeAddress(0)) {
 248  E :        ExportInfo info;
 249  E :        info.ordinal = index + 1;
 250    :  
 251  E :        RelativeAddress function = functions[index];
 252    :        // Is it a forward?
 253  E :        if (function >= addr && function < end) {
 254  E :          if (!ReadImageString(function, &info.forward)) {
 255  i :            LOG(ERROR) << "Unable to read export forward string.";
 256  i :            return false;
 257    :          }
 258  E :        } else {
 259  E :          info.function = function;
 260    :        }
 261    :  
 262    :        // Does it have a name?
 263  E :        for (uint16_t i = 0; i < export_dir->NumberOfNames; ++i) {
 264  E :          if (name_ordinals[i] == index) {
 265  E :            if (!ReadImageString(names[i], &info.name)) {
 266  i :              LOG(ERROR) << "Unable to read export name.";
 267  i :              return false;
 268    :            }
 269  E :            break;
 270    :          }
 271  E :        }
 272    :  
 273  E :        exports->push_back(info);
 274  E :      }
 275  E :    }
 276    :  
 277  E :    return true;
 278  E :  }
 279    :  
 280    :  template <class ImageNtHeaders, DWORD MagicValidation>
 281    :  bool PEFileBase<ImageNtHeaders, MagicValidation>::Translate(
 282  E :      RelativeAddress rel, AbsoluteAddress* abs) const {
 283  E :    DCHECK_NE(static_cast<AbsoluteAddress*>(NULL), abs);
 284  E :    if (rel.value() >= nt_headers_->OptionalHeader.SizeOfImage)
 285  E :      return false;
 286  E :    abs->set_value(rel.value() + nt_headers_->OptionalHeader.ImageBase);
 287  E :    return true;
 288  E :  }
 289    :  
 290    :  template <class ImageNtHeaders, DWORD MagicValidation>
 291    :  bool PEFileBase<ImageNtHeaders, MagicValidation>::Translate(
 292  E :      AbsoluteAddress abs, RelativeAddress* rel) const {
 293  E :    DCHECK_NE(static_cast<RelativeAddress*>(NULL), rel);
 294  E :    uintptr_t rel_addr = AbsToRelDisplacement(abs.value());
 295  E :    if (rel_addr >= nt_headers_->OptionalHeader.SizeOfImage)
 296  E :      return false;
 297  E :    rel->set_value(rel_addr);
 298  E :    return true;
 299  E :  }
 300    :  
 301    :  template <class ImageNtHeaders, DWORD MagicValidation>
 302    :  bool PEFileBase<ImageNtHeaders, MagicValidation>::Translate(
 303  E :      FileOffsetAddress offs, RelativeAddress* rel) const {
 304  E :    DCHECK_NE(static_cast<RelativeAddress*>(NULL), rel);
 305    :  
 306    :    // The first "previous section" is the headers.
 307  E :    RelativeAddress previous_section_start(0);
 308  E :    FileOffsetAddress previous_section_file_start(0);
 309  E :    const IMAGE_SECTION_HEADER* previous_section = NULL;
 310  E :    for (size_t i = 0; i < nt_headers_->FileHeader.NumberOfSections; ++i) {
 311  E :      if (offs.value() < section_headers_[i].PointerToRawData)
 312  E :        break;
 313    :  
 314  E :      previous_section_start.set_value(section_headers_[i].VirtualAddress);
 315  E :      previous_section_file_start.set_value(
 316    :          section_headers_[i].PointerToRawData);
 317  E :      previous_section = section_headers_ + i;
 318  E :    }
 319    :  
 320  E :    size_t section_offset = offs - previous_section_file_start;
 321  E :    if (previous_section != NULL &&
 322    :        section_offset >= previous_section->SizeOfRawData) {
 323  E :      return false;
 324    :    }
 325    :  
 326  E :    *rel = previous_section_start + section_offset;
 327    :  
 328  E :    return true;
 329  E :  }
 330    :  
 331    :  template <class ImageNtHeaders, DWORD MagicValidation>
 332    :  bool PEFileBase<ImageNtHeaders, MagicValidation>::Translate(
 333  E :      RelativeAddress rel, FileOffsetAddress* offs) const {
 334  E :    DCHECK_NE(static_cast<FileOffsetAddress*>(NULL), offs);
 335    :  
 336    :    // In the headers?
 337  E :    if (rel.value() < section_header(0)->VirtualAddress) {
 338  E :      offs->set_value(rel.value());
 339  E :      return true;
 340    :    }
 341    :  
 342    :    // Find the section in which this address lies.
 343  E :    const IMAGE_SECTION_HEADER* section = GetSectionHeader(rel, 1);
 344  E :    if (section == NULL)
 345  E :      return false;
 346    :  
 347    :    // Calculate the offset of this address and ensure it can be expressed as
 348    :    // a file offset (lies in the explicit data part of the section, not the
 349    :    // implicit virtual data at the end).
 350  E :    size_t section_offset = rel.value() - section->VirtualAddress;
 351  E :    if (section_offset >= section->SizeOfRawData)
 352  E :      return false;
 353    :  
 354  E :    offs->set_value(section->PointerToRawData + section_offset);
 355    :  
 356  E :    return true;
 357  E :  }
 358    :  
 359    :  template <class ImageNtHeaders, DWORD MagicValidation>
 360    :  bool PEFileBase<ImageNtHeaders, MagicValidation>::Translate(
 361    :      RelativeAddress relative_address,
 362  E :      SectionOffsetAddress* section_offset_address) const {
 363  E :    DCHECK_NE(static_cast<SectionOffsetAddress*>(NULL), section_offset_address);
 364    :  
 365    :    // In the headers?
 366  E :    if (relative_address.value() < section_header(0)->VirtualAddress) {
 367  E :      section_offset_address->set_section_id(0);
 368  E :      section_offset_address->set_offset(relative_address.value());
 369  E :      return true;
 370    :    }
 371    :  
 372    :    // Find the section in which this address lies.
 373  E :    size_t section_id = GetSectionIndex(relative_address, 1);
 374  E :    if (section_id == kInvalidSection)
 375  i :      return false;
 376  E :    const IMAGE_SECTION_HEADER* section = section_header(section_id);
 377    :  
 378    :    // Calculate the offset of this address and ensure it can be expressed as
 379    :    // a section offset (lies in the explicit data part of the section, not the
 380    :    // implicit virtual data at the end).
 381  E :    uint32_t section_offset = relative_address.value() - section->VirtualAddress;
 382  E :    if (section_offset >= section->SizeOfRawData)
 383  i :      return false;
 384    :  
 385    :    // The offset of the first explicitly defined section is 1. The index 0
 386    :    // is used for addresses before the first section.
 387  E :    section_offset_address->set_section_id(section_id + 1);
 388  E :    section_offset_address->set_offset(section_offset);
 389    :  
 390  E :    return true;
 391  E :  }
 392    :  
 393    :  template <class ImageNtHeaders, DWORD MagicValidation>
 394    :  bool PEFileBase<ImageNtHeaders, MagicValidation>::ReadImage(
 395  E :      AbsoluteAddress addr, void* data, size_t len) const {
 396  E :    RelativeAddress rel;
 397  E :    if (!Translate(addr, &rel))
 398  i :      return false;
 399    :  
 400  E :    return ReadImage(rel, data, len);
 401  E :  }
 402    :  
 403    :  template <class ImageNtHeaders, DWORD MagicValidation>
 404    :  bool PEFileBase<ImageNtHeaders, MagicValidation>::ReadImageString(
 405  E :      AbsoluteAddress addr, std::string* str) const {
 406  E :    RelativeAddress rel;
 407  E :    if (!Translate(addr, &rel))
 408  i :      return false;
 409    :  
 410  E :    return ReadImageString(rel, str);
 411  E :  }
 412    :  
 413    :  template <class ImageNtHeaders, DWORD MagicValidation>
 414    :  const uint8_t* PEFileBase<ImageNtHeaders, MagicValidation>::GetImageData(
 415    :      AbsoluteAddress addr,
 416  E :      size_t len) const {
 417  E :    RelativeAddress rel;
 418  E :    if (Translate(addr, &rel))
 419  E :      return GetImageData(rel, len);
 420    :  
 421  i :    return NULL;
 422  E :  }
 423    :  
 424    :  template <class ImageNtHeaders, DWORD MagicValidation>
 425    :  uint8_t* PEFileBase<ImageNtHeaders, MagicValidation>::GetImageData(
 426    :      AbsoluteAddress addr,
 427  E :      size_t len) {
 428  E :    return const_cast<uint8_t*>(
 429    :        static_cast<const PEFileBase<ImageNtHeaders, MagicValidation>*>(this)
 430    :            ->GetImageData(addr, len));
 431  E :  }
 432    :  
 433    :  template <class ImageNtHeaders, DWORD MagicValidation>
 434    :  bool PEFileBase<ImageNtHeaders, MagicValidation>::Contains(AbsoluteAddress addr,
 435  E :                                                             size_t len) const {
 436  E :    RelativeAddress rel;
 437  E :    return Translate(addr, &rel) && Contains(rel, len);
 438  E :  }
 439    :  
 440    :  template <class ImageNtHeaders, DWORD MagicValidation>
 441    :  size_t PEFileBase<ImageNtHeaders, MagicValidation>::GetSectionIndex(
 442  E :      AbsoluteAddress addr, size_t len) const {
 443  E :    RelativeAddress rel;
 444  E :    if (!Translate(addr, &rel))
 445  E :      return kInvalidSection;
 446  E :    return GetSectionIndex(rel, len);
 447  E :  }
 448    :  
 449    :  template <class ImageNtHeaders, DWORD MagicValidation>
 450    :  const IMAGE_SECTION_HEADER* PEFileBase<ImageNtHeaders,
 451    :                                         MagicValidation>::GetSectionHeader(
 452  E :      AbsoluteAddress addr, size_t len) const {
 453  E :    RelativeAddress rel;
 454  E :    if (!Translate(addr, &rel))
 455  i :      return NULL;
 456  E :    return GetSectionHeader(rel, len);
 457  E :  }
 458    :  
 459    :  template <class ImageNtHeaders, DWORD MagicValidation>
 460    :  size_t PEFileBase<ImageNtHeaders, MagicValidation>::GetSectionIndex(
 461  E :      const char* name) const {
 462  E :    size_t section_count = file_header_->NumberOfSections;
 463  E :    for (size_t i = 0; i < section_count; ++i) {
 464  E :      const IMAGE_SECTION_HEADER* header = section_headers_ + i;
 465    :      if (strncmp(reinterpret_cast<const char*>(header->Name), name,
 466  E :                  IMAGE_SIZEOF_SHORT_NAME) == 0)
 467  E :        return i;
 468  E :    }
 469  E :    return kInvalidSection;
 470  E :  }
 471    :  
 472    :  template <class ImageNtHeaders, DWORD MagicValidation>
 473    :  const IMAGE_SECTION_HEADER* PEFileBase<ImageNtHeaders,
 474    :                                         MagicValidation>::GetSectionHeader(
 475  E :      const char* name) const {
 476  E :    size_t id = GetSectionIndex(name);
 477  E :    if (id == kInvalidSection)
 478  E :      return NULL;
 479  E :    return section_headers_ + id;
 480  E :  }
 481    :  
 482    :  template <class ImageNtHeaders, DWORD MagicValidation>
 483    :  const IMAGE_DOS_HEADER* PEFileBase<ImageNtHeaders,
 484  E :                                     MagicValidation>::dos_header() const {
 485  E :    return dos_header_;
 486  E :  }
 487    :  
 488    :  template <class ImageNtHeaders, DWORD MagicValidation>
 489    :  const ImageNtHeaders* PEFileBase<ImageNtHeaders,
 490  E :                                   MagicValidation>::nt_headers() const {
 491  E :    return nt_headers_;
 492  E :  }
 493    :  
 494    :  template <class ImageNtHeaders, DWORD MagicValidation>
 495    :  size_t PEFileBase<ImageNtHeaders, MagicValidation>::AbsToRelDisplacement(
 496  E :      size_t abs_disp) const {
 497  E :    return abs_disp - nt_headers_->OptionalHeader.ImageBase;
 498  E :  }
 499    :  
 500    :  template <class ImageNtHeaders, DWORD MagicValidation>
 501  E :  bool PEFileBase<ImageNtHeaders, MagicValidation>::ReadHeaders() {
 502    :    // Read the DOS header.
 503  E :    if (!parser_.GetAt(0, &dos_header_))
 504  i :      return false;
 505    :  
 506    :    // And the NT headers, checking alignment.
 507  E :    FileOffsetAddress nt_off(dos_header_->e_lfanew);
 508  E :    if (!parser_.GetAt(nt_off.value(), &nt_headers_))
 509  i :      return false;
 510    :  
 511  E :    FileOffsetAddress file_header_start(dos_header_->e_lfanew +
 512    :                                        offsetof(ImageNtHeaders, FileHeader));
 513  E :    if (!ReadCommonHeaders(file_header_start))
 514  i :      return false;
 515    :  
 516  E :    return nt_headers_->OptionalHeader.Magic == MagicValidation;
 517  E :  }
 518    :  
 519    :  template<class ImageNtHeaders, DWORD MagicValidation>
 520    :  bool PEFileBase<ImageNtHeaders, MagicValidation>::Signature::IsConsistent(
 521  E :      const Signature& signature) const {
 522  E :    return IsConsistentExceptForChecksum(signature) &&
 523    :        module_checksum == signature.module_checksum;
 524  E :  }
 525    :  
 526    :  template<class ImageNtHeaders, DWORD MagicValidation>
 527    :  bool PEFileBase<ImageNtHeaders,
 528    :                  MagicValidation>::Signature::IsConsistentExceptForChecksum(
 529  E :      const Signature& signature) const {
 530  E :    return base_address == signature.base_address &&
 531    :        module_size == signature.module_size &&
 532    :        module_time_date_stamp == signature.module_time_date_stamp;
 533  E :  }
 534    :  
 535    :  template<class ImageNtHeaders, DWORD MagicValidation>
 536    :  bool PEFileBase<ImageNtHeaders, MagicValidation>::Signature::operator==(
 537  E :      const Signature& signature) const {
 538  E :    return path == signature.path && IsConsistent(signature);
 539  E :  }
 540    :  
 541    :  template<class ImageNtHeaders, DWORD MagicValidation>
 542    :  bool PEFileBase<ImageNtHeaders, MagicValidation>::Signature::Save(
 543  E :      core::OutArchive* out_archive) const {
 544  E :    return out_archive->Save(path) &&
 545    :        out_archive->Save(base_address) &&
 546    :        out_archive->Save(module_size) &&
 547    :        out_archive->Save(module_time_date_stamp) &&
 548    :        out_archive->Save(module_checksum);
 549  E :  }
 550    :  
 551    :  template<class ImageNtHeaders, DWORD MagicValidation>
 552    :  bool PEFileBase<ImageNtHeaders, MagicValidation>::Signature::Load(
 553  E :      core::InArchive* in_archive) {
 554  E :    return in_archive->Load(&path) &&
 555    :        in_archive->Load(&base_address) &&
 556    :        in_archive->Load(&module_size) &&
 557    :        in_archive->Load(&module_time_date_stamp) &&
 558    :        in_archive->Load(&module_checksum);
 559  E :  }
 560    :  
 561    :  }  // namespace pe
 562    :  
 563    :  #endif  // SYZYGY_PE_PE_FILE_IMPL_H_

Coverage information generated Fri Jul 29 11:00:21 2016.