Coverage for /Syzygy/pe/pe_file_impl.h

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

Coverage information generated Thu Mar 26 16:15:41 2015.