Coverage for /Syzygy/pe/pe_file.cc

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

Coverage information generated Thu Jul 04 09:34:53 2013.