Coverage for /Syzygy/pe/pe_file.cc

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

Line-by-line coverage:

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

Coverage information generated Thu Sep 06 11:30:46 2012.