Coverage for /Syzygy/pe/pe_file_parser.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
67.3%4226270.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    :  #include "syzygy/pe/pe_file_parser.h"
  16    :  
  17    :  // The Win8 SDK defines this in winerror.h, and it is subsequently redefined by
  18    :  // delayimp.h
  19    :  #undef FACILITY_VISUALCPP
  20    :  #include <delayimp.h>
  21    :  
  22    :  #include "base/bind.h"
  23    :  #include "base/strings/stringprintf.h"
  24    :  #include "syzygy/common/align.h"
  25    :  #include "syzygy/pe/pe_structs.h"
  26    :  
  27    :  namespace pe {
  28    :  
  29    :  namespace {
  30    :  
  31    :  using block_graph::BlockGraph;
  32    :  using core::AbsoluteAddress;
  33    :  using core::FileOffsetAddress;
  34    :  using core::RelativeAddress;
  35    :  
  36    :  const char* kDirEntryNames[] = {
  37    :      "IMAGE_DIRECTORY_ENTRY_EXPORT",
  38    :      "IMAGE_DIRECTORY_ENTRY_IMPORT",
  39    :      "IMAGE_DIRECTORY_ENTRY_RESOURCE",
  40    :      "IMAGE_DIRECTORY_ENTRY_EXCEPTION",
  41    :      "IMAGE_DIRECTORY_ENTRY_SECURITY",
  42    :      "IMAGE_DIRECTORY_ENTRY_BASERELOC",
  43    :      "IMAGE_DIRECTORY_ENTRY_DEBUG",
  44    :      "IMAGE_DIRECTORY_ENTRY_ARCHITECTURE",
  45    :      "IMAGE_DIRECTORY_ENTRY_GLOBALPTR",
  46    :      "IMAGE_DIRECTORY_ENTRY_TLS",
  47    :      "IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG",
  48    :      "IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT",
  49    :      "IMAGE_DIRECTORY_ENTRY_IAT",
  50    :      "IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT",
  51    :      "IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR",
  52    :  };
  53    :  
  54    :  // Given a table type, and whether or not it is bound, returns the type of
  55    :  // data we can expect to find in the table.
  56    :  PEFileParser::ThunkDataType GetThunkDataType(
  57  E :      PEFileParser::ThunkTableType table_type, bool is_bound) {
  58  E :    switch (table_type) {
  59    :      case PEFileParser::kImportNameTable:
  60  E :        return PEFileParser::kImageThunkData;
  61    :  
  62    :      case PEFileParser::kImportAddressTable:
  63  E :        if (is_bound)
  64  i :          return PEFileParser::kCodeOutOfImageThunkData;
  65  i :        else
  66  E :          return PEFileParser::kImageThunkData;
  67    :  
  68    :      case PEFileParser::kDelayLoadImportNameTable:
  69  E :        return PEFileParser::kImageThunkData;
  70    :  
  71    :      case PEFileParser::kDelayLoadImportAddressTable:
  72  E :        return PEFileParser::kCodeInImageThunkData;
  73    :  
  74    :      case PEFileParser::kDelayLoadBoundImportAddressTable:
  75  E :        return PEFileParser::kArbitraryThunkData;
  76    :  
  77    :      default: break;
  78    :    }
  79  i :    NOTREACHED() << "Unknown ThunkDataType.";
  80  i :    return PEFileParser::kArbitraryThunkData;
  81  E :  }
  82    :  
  83    :  bool DummyOnImportThunk(const char* module_name,
  84    :                          const char* symbol_name,
  85  E :                          BlockGraph::Block* thunk) {
  86  E :    return true;
  87  E :  }
  88    :  
  89    :  }  // namespace
  90    :  
  91    :  // This class represents a generic, untyped pointer with a fixed length,
  92    :  // into a PE image at a particular address.
  93    :  class PEFilePtr {
  94    :   public:
  95  E :    PEFilePtr() : ptr_(NULL), len_(0) {
  96  E :    }
  97    :  
  98    :    // Set the pointer to the address and data in @p block.
  99  E :    bool Set(BlockGraph::Block* block) {
 100  E :      return Set(block, block->addr());
 101  E :    }
 102    :  
 103    :    // Set the pointer to the address @p addr, which must be contained
 104    :    // within @p block, and the corresponding data in @p block.
 105  E :    bool Set(BlockGraph::Block* block, RelativeAddress addr) {
 106  E :      const uint8_t* ptr = block->data();
 107  E :      ptrdiff_t offs = addr - block->addr();
 108  E :      if (ptr == NULL || offs < 0)
 109  i :        return false;
 110  E :      if (static_cast<size_t>(offs) >= block->data_size())
 111  i :        return false;
 112    :  
 113  E :      addr_ = addr;
 114  E :      ptr_ = ptr + offs;
 115  E :      len_ = block->data_size() - offs;
 116    :  
 117  E :      return true;
 118  E :    }
 119    :  
 120    :    // Set the pointer to the address @p addr, and length @p len,
 121    :    // iff the @p image contains that data.
 122  E :    bool Read(const PEFile& image, RelativeAddress addr, size_t len) {
 123  E :      const uint8_t* ptr = image.GetImageData(addr, len);
 124  E :      if (ptr == NULL)
 125  i :        return false;
 126    :  
 127    :      // Success - store the data we now point to.
 128  E :      addr_ = addr;
 129  E :      ptr_ = ptr;
 130  E :      len_ = len;
 131    :  
 132  E :      return true;
 133  E :    }
 134    :  
 135    :    // Advance the pointer by @p len bytes iff the pointer points to at
 136    :    // least @len bytes.
 137  E :    bool Advance(size_t len) {
 138    :      // Do we have enough remaining?
 139  E :      if (len_ < len)
 140  i :        return false;
 141    :  
 142    :      // Walk forward, and trim the remaining length.
 143  E :      addr_ += len;
 144  E :      ptr_ += len;
 145  E :      len_ -= len;
 146    :  
 147  E :      return true;
 148  E :    }
 149    :  
 150    :    // Accessors.
 151  E :    RelativeAddress addr() const { return addr_; }
 152    :    void set_addr(RelativeAddress addr) { addr_ = addr; }
 153    :  
 154  E :    const uint8_t* ptr() const { return ptr_; }
 155    :    void set_ptr(const uint8_t* ptr) { ptr_ = ptr; }
 156    :  
 157  E :    size_t len() const { return len_; }
 158    :    void set_len(size_t len) { len_ = len; }
 159    :  
 160    :   private:
 161    :    RelativeAddress addr_;
 162    :    const uint8_t* ptr_;
 163    :    size_t len_;
 164    :  };
 165    :  
 166    :  // Represents a typed pointer into a PE image at a given address.
 167    :  // The data pointed to by a struct ptr is typically at least sizeof(ItemType),
 168    :  // but may be less when parsing structures that have grown over time.
 169    :  template <typename ItemType>
 170    :  class PEFileStructPtr {
 171    :   public:
 172  E :    PEFileStructPtr() {
 173  E :    }
 174    :  
 175    :    // Set this pointer to the address and data in @p block.
 176    :    // @returns true iff successful.
 177  E :    bool Set(BlockGraph::Block* block) {
 178  E :      if (block->data_size() < sizeof(ItemType))
 179  i :        return false;
 180    :  
 181  E :      return ptr_.Set(block);
 182  E :    }
 183    :  
 184    :    // Set this pointer to the address and data in @p block, without checking
 185    :    // the block length.
 186    :    // @note the caller assumes responsibility for not accessing fields
 187    :    //    beyond the block length.
 188    :    // @returns true iff successful.
 189  E :    bool SetUnchecked(BlockGraph::Block* block) {
 190  E :      return ptr_.Set(block);
 191  E :    }
 192    :  
 193    :    // Set this pointer to addr, which must be contained within @p block,
 194    :    // and the corresponding data in @p block.
 195    :    // @returns true iff successful.
 196  E :    bool Set(BlockGraph::Block* block, RelativeAddress addr) {
 197  E :      if (block->data_size() < sizeof(ItemType))
 198  i :        return false;
 199    :  
 200  E :      return ptr_.Set(block, addr);
 201  E :    }
 202    :  
 203    :    // Read data from @p image at @p addr.
 204  E :    bool Read(const PEFile& image, RelativeAddress addr) {
 205  E :      return Read(image, addr, sizeof(ItemType));
 206  E :    }
 207    :  
 208    :    // Read @p len data bytes from @p image at @p addr.
 209    :    // @note @p len must be greater or equal to sizeof(ItemType).
 210  E :    bool Read(const PEFile& image, RelativeAddress addr, size_t len) {
 211  E :      DCHECK(len >= sizeof(ItemType));
 212  E :      return ptr_.Read(image, addr, len);
 213  E :    }
 214    :  
 215    :    // Advance our pointer by sizeof(ItemType) iff this would leave
 216    :    // this pointer valid.
 217  E :    bool Next() {
 218  E :      DCHECK(IsValid());
 219    :  
 220    :      // See whether there's enough room left for another full item.
 221  E :      size_t new_len = ptr_.len() - sizeof(ItemType);
 222  E :      if (new_len < sizeof(ItemType))
 223  E :        return false;
 224    :  
 225    :      // Walk forward one item. We've already checked that there's
 226    :      // sufficient data left, so this must succeed.
 227  E :      bool ret = ptr_.Advance(sizeof(ItemType));
 228  E :      DCHECK(ret && IsValid());
 229    :  
 230  E :      return true;
 231  E :    }
 232    :  
 233  E :    RelativeAddress addr() const { return ptr_.addr(); }
 234    :    void set_addr(RelativeAddress addr) { ptr.set_addr(addr); }
 235    :  
 236  E :    const ItemType* ptr() const {
 237  E :      return reinterpret_cast<const ItemType*>(ptr_.ptr());
 238  E :    }
 239    :  
 240  E :    const ItemType* operator->() const {
 241  E :      return ptr();
 242  E :    }
 243    :  
 244    :    // Returns the image address of the data at ptr.
 245    :    // @note ptr must be within the data we point to.
 246  E :    RelativeAddress AddressOf(const void* ptr) const {
 247  E :      DCHECK(IsValid());
 248    :  
 249  E :      const uint8_t* tmp = reinterpret_cast<const uint8_t*>(ptr);
 250  E :      DCHECK(tmp >= ptr_.ptr());
 251  E :      ptrdiff_t offs = tmp - ptr_.ptr();
 252  E :      DCHECK(offs >= 0 && static_cast<size_t>(offs) < ptr_.len());
 253    :  
 254  E :      return ptr_.addr() + offs;
 255  E :    }
 256    :  
 257  E :    size_t len() const { return ptr_.len(); }
 258    :  
 259    :   private:
 260    :    // @returns true iff this pointer is valid.
 261  E :    bool IsValid() const {
 262  E :      return ptr_.ptr() != NULL;
 263  E :    }
 264    :  
 265    :    PEFilePtr ptr_;
 266    :  
 267    :    DISALLOW_COPY_AND_ASSIGN(PEFileStructPtr);
 268    :  };
 269    :  
 270    :  PEFileParser::PEFileParser(const PEFile& image_file,
 271    :                             BlockGraph::AddressSpace* address_space,
 272    :                             const AddReferenceCallback& add_reference)
 273  E :      : image_file_(image_file),
 274  E :        address_space_(address_space),
 275  E :        add_reference_(add_reference),
 276  E :        on_import_thunk_(base::Bind(&DummyOnImportThunk)) {
 277  E :    DCHECK(!add_reference.is_null());
 278  E :  }
 279    :  
 280    :  const PEFileParser::DataDirParseEntry PEFileParser::parsers_[] = {
 281    :    {
 282    :      IMAGE_DIRECTORY_ENTRY_EXPORT,
 283    :      "export",
 284    :      &PEFileParser::ParseExportDir
 285    :    }, {
 286    :      // We parse the IAT ahead of the imports because if the IAT entry is
 287    :      // present, we want it chunked and ready to reference before we start
 288    :      // parsing imports.
 289    :      IMAGE_DIRECTORY_ENTRY_IAT,
 290    :      "iat",
 291    :      &PEFileParser::ParseIatDir
 292    :    }, {
 293    :      IMAGE_DIRECTORY_ENTRY_IMPORT,
 294    :      "import",
 295    :      &PEFileParser::ParseImportDir
 296    :    }, {
 297    :      IMAGE_DIRECTORY_ENTRY_RESOURCE,
 298    :      "resource",
 299    :      &PEFileParser::ParseResourceDir
 300    :    }, {
 301    :      IMAGE_DIRECTORY_ENTRY_EXCEPTION,
 302    :      "exception",
 303    :      &PEFileParser::ParseExceptionDir
 304    :    }, {
 305    :      IMAGE_DIRECTORY_ENTRY_SECURITY,
 306    :      "security",
 307    :      &PEFileParser::ParseSecurityDir
 308    :    }, {
 309    :      IMAGE_DIRECTORY_ENTRY_BASERELOC,
 310    :      "relocs",
 311    :      &PEFileParser::ParseRelocDir
 312    :    }, {
 313    :      IMAGE_DIRECTORY_ENTRY_DEBUG,
 314    :      "debug",
 315    :      &PEFileParser::ParseDebugDir
 316    :    }, {
 317    :      IMAGE_DIRECTORY_ENTRY_ARCHITECTURE,
 318    :      "architecture",
 319    :      &PEFileParser::ParseArchitectureDir
 320    :    }, {
 321    :      IMAGE_DIRECTORY_ENTRY_GLOBALPTR,
 322    :      "global",
 323    :      &PEFileParser::ParseGlobalDir
 324    :    }, {
 325    :      IMAGE_DIRECTORY_ENTRY_TLS,
 326    :      "tls",
 327    :      &PEFileParser::ParseTlsDir
 328    :    }, {
 329    :      IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
 330    :      "load config",
 331    :      &PEFileParser::ParseLoadConfigDir
 332    :    }, {
 333    :      IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT,
 334    :      "bound import",
 335    :      &PEFileParser::ParseBoundImportDir
 336    :    }, {
 337    :      IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT,
 338    :      "delay import",
 339    :      &PEFileParser::ParseDelayImportDir
 340    :    }, {
 341    :      IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR,
 342    :      "com descriptor",
 343    :      &PEFileParser::ParseComDescriptorDir
 344    :    },
 345    :  };
 346    :  
 347  E :  bool PEFileParser::ParseImage(PEHeader* pe_header) {
 348  E :    if (!ParseImageHeader(pe_header)) {
 349  i :      LOG(ERROR) << "Unable to parse image header.";
 350  i :      return false;
 351    :    }
 352    :  
 353  E :    for (size_t i = 0; i < arraysize(parsers_); ++i) {
 354  E :      const DataDirParseEntry& parser = parsers_[i];
 355  E :      DCHECK(parser.entry < IMAGE_NUMBEROF_DIRECTORY_ENTRIES);
 356  E :      DCHECK(parser.parser != NULL);
 357  E :      DCHECK(parser.name != NULL);
 358    :  
 359  E :      const IMAGE_DATA_DIRECTORY& entry =
 360    :          image_file_.nt_headers()->OptionalHeader.DataDirectory[parser.entry];
 361    :  
 362  E :      if (entry.Size != 0) {
 363  E :        DCHECK(entry.VirtualAddress != 0);
 364    :  
 365    :        // TODO(chrisha): Once ImageLayout/AddressSpace/etc. can support blocks
 366    :        // that are not mappable, then support this properly. In the meantime
 367    :        // simply ignore the security directory entry entirely and null it out so
 368    :        // that the toolchain doesn't produce binaries with bad signatures.
 369  E :        if (parser.entry == IMAGE_DIRECTORY_ENTRY_SECURITY) {
 370  E :          LOG(WARNING) << "Ignoring security directory (image signature)!";
 371  E :          uint8_t* data = pe_header->nt_headers->GetMutableData();
 372  E :          DCHECK_NE(static_cast<uint8_t*>(nullptr), data);
 373    :          IMAGE_NT_HEADERS* nt_headers =
 374  E :              reinterpret_cast<IMAGE_NT_HEADERS*>(data);
 375  E :          auto& data_dir = nt_headers->OptionalHeader.DataDirectory[parser.entry];
 376  E :          data_dir.Size = 0;
 377  E :          data_dir.VirtualAddress = 0;
 378  E :        } else {
 379  E :          BlockGraph::Block* block = (this->*parser.parser)(entry);
 380  E :          if (block == nullptr) {
 381  i :            LOG(ERROR) << "Failed to parse data directory " << parser.name << ".";
 382  i :            return false;
 383    :          }
 384    :  
 385  E :          pe_header->data_directory[parser.entry] = block;
 386    :        }
 387    :      }
 388  E :    }
 389    :  
 390  E :    return true;
 391  E :  }
 392    :  
 393  E :  bool PEFileParser::ParseImageHeader(PEHeader* header) {
 394    :    // Get the start of the image headers.
 395    :    size_t dos_header_size =
 396  E :        reinterpret_cast<const uint8_t*>(image_file_.nt_headers()) -
 397    :        reinterpret_cast<const uint8_t*>(image_file_.dos_header());
 398    :  
 399  E :    if (dos_header_size < sizeof(IMAGE_DOS_HEADER)) {
 400  i :      LOG(ERROR) << "Impossibly small DOS header.";
 401  i :      return false;
 402    :    }
 403    :  
 404  E :    PEFileStructPtr<IMAGE_DOS_HEADER> dos_header_ptr;
 405  E :    if (!dos_header_ptr.Read(image_file_, RelativeAddress(0), dos_header_size)) {
 406  i :      LOG(ERROR) << "No DOS header in image.";
 407  i :      return false;
 408    :    }
 409    :  
 410    :    // The length of the DOS header is the address of the NT headers.
 411  E :    RelativeAddress nt_headers_address(dos_header_size);
 412  E :    DCHECK(nt_headers_address.value() > sizeof(IMAGE_DOS_HEADER));
 413    :  
 414    :    // Chunk out the DOS header and stub.
 415  E :    BlockGraph::Block* dos_header = AddBlock(BlockGraph::DATA_BLOCK,
 416    :                                             RelativeAddress(0),
 417    :                                             nt_headers_address.value(),
 418    :                                             "DOS Header");
 419  E :    if (dos_header == NULL) {
 420  i :      LOG(ERROR) << "Unable to add DOS header block.";
 421  i :      return false;
 422    :    }
 423    :  
 424    :    // Add the reference to the PE header. This reference can be interpreted
 425    :    // either as a disk or a relative reference, as disk and relative addresses
 426    :    // coincide in the image header.
 427    :    static_assert(sizeof(DWORD) == sizeof(dos_header_ptr->e_lfanew),
 428    :                  "dos_header_ptr->e_lfanew size is wrong.");
 429  E :    if (!AddRelative(dos_header_ptr,
 430    :                     reinterpret_cast<const DWORD*>(&dos_header_ptr->e_lfanew))) {
 431  i :      LOG(ERROR) << "Unable to add DOS to NT headers reference.";
 432  i :      return false;
 433    :    }
 434    :  
 435  E :    PEFileStructPtr<IMAGE_NT_HEADERS> nt_headers_ptr;
 436  E :    if (!nt_headers_ptr.Read(image_file_, nt_headers_address)) {
 437  i :      LOG(ERROR) << "Unable to read NT headers.";
 438  i :      return false;
 439    :    }
 440    :  
 441  E :    for (size_t i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; ++i) {
 442  E :      if (!AddRelative(nt_headers_ptr,
 443    :              &nt_headers_ptr->OptionalHeader.DataDirectory[i].VirtualAddress)) {
 444  i :        LOG(ERROR) << "Unable to add data directory reference for "
 445    :                   << kDirEntryNames[i];
 446  i :        return false;
 447    :      }
 448  E :    }
 449    :  
 450    :    // Calculate the size of the NT headers and section headers.
 451  E :    size_t nt_headers_size = sizeof(IMAGE_NT_HEADERS) +
 452    :        nt_headers_ptr->FileHeader.NumberOfSections *
 453    :            sizeof(IMAGE_SECTION_HEADER);
 454    :    // Chunk the NT & section headers.
 455  E :    BlockGraph::Block* nt_headers = AddBlock(BlockGraph::DATA_BLOCK,
 456    :                                             nt_headers_address,
 457    :                                             nt_headers_size,
 458    :                                             "NT Headers");
 459  E :    if (nt_headers == NULL) {
 460  i :      LOG(ERROR) << "Unable to add NT Headers block.";
 461  i :      return false;
 462    :    }
 463    :  
 464  E :    if (!AddRelative(nt_headers_ptr,
 465    :                     &nt_headers_ptr->OptionalHeader.AddressOfEntryPoint)) {
 466  i :      LOG(ERROR) << "Unable to add entry point reference.";
 467  i :      return false;
 468    :    }
 469    :  
 470  E :    if (header != NULL) {
 471  E :      header->dos_header = dos_header;
 472  E :      header->nt_headers = nt_headers;
 473    :    }
 474    :  
 475  E :    return true;
 476  E :  }
 477    :  
 478    :  BlockGraph::Block* PEFileParser::ParseExportDir(
 479  E :      const IMAGE_DATA_DIRECTORY& dir) {
 480    :    BlockGraph::Block* export_dir_block =
 481  E :        AddBlock(BlockGraph::DATA_BLOCK,
 482    :                 RelativeAddress(dir.VirtualAddress),
 483    :                 dir.Size,
 484    :                 "Export Directory");
 485  E :    if (export_dir_block == NULL) {
 486  i :      LOG(ERROR) << "Failed to create export directory block.";
 487  i :      return NULL;
 488    :    }
 489    :  
 490  E :    PEFileStructPtr<IMAGE_EXPORT_DIRECTORY> export_dir;
 491  E :    if (!export_dir.Set(export_dir_block)) {
 492  i :      LOG(ERROR) << "Unable to read export directory.";
 493  i :      return NULL;
 494    :    }
 495    :  
 496  E :    if (!AddRelative(export_dir, &export_dir->Name)) {
 497  i :      LOG(ERROR) << "Unable to add export functions reference.";
 498  i :      return NULL;
 499    :    }
 500    :  
 501    :    // All the references in the export directory should point back into
 502    :    // the export directory, unless they are NULL (empty).
 503    :  
 504  E :    if (export_dir->AddressOfFunctions != 0) {
 505  E :      DCHECK_EQ(export_dir_block, address_space_->GetContainingBlock(
 506    :          RelativeAddress(export_dir->AddressOfFunctions),
 507  E :          sizeof(RelativeAddress)));
 508  E :      if (!AddRelative(export_dir, &export_dir->AddressOfFunctions)) {
 509  i :        LOG(ERROR) << "Unable to add export functions reference.";
 510  i :        return NULL;
 511    :      }
 512    :  
 513  E :      PEFileStructPtr<DWORD> function;
 514  E :      if (!function.Set(export_dir_block,
 515    :                        RelativeAddress(export_dir->AddressOfFunctions))) {
 516  i :        LOG(ERROR) << "Unable to parse export function table.";
 517  i :        return NULL;
 518    :      }
 519    :  
 520  E :      for (size_t i = 0; i < export_dir->NumberOfFunctions; ++i) {
 521    :        // TODO(siggi): This could be labeled with the exported function's
 522    :        //    name, if one is available.
 523  E :        if (!AddRelative(function, function.ptr())) {
 524  i :          LOG(ERROR) << "Unable to add reference to exported function.";
 525  i :          return NULL;
 526    :        }
 527    :  
 528  E :        if (!function.Next()) {
 529  i :          LOG(ERROR) << "Unable to parse export function table.";
 530  i :          return NULL;
 531    :        }
 532  E :      }
 533    :    }
 534    :  
 535  E :    if (export_dir->AddressOfNames != 0) {
 536  E :      DCHECK_EQ(export_dir_block, address_space_->GetContainingBlock(
 537    :          RelativeAddress(export_dir->AddressOfNames),
 538  E :          sizeof(RelativeAddress)));
 539  E :      if (!AddRelative(export_dir, &export_dir->AddressOfNames)) {
 540  i :        LOG(ERROR) << "Unable to add export address of names reference.";
 541  i :        return NULL;
 542    :      }
 543    :  
 544    :      // Add references to the export function names.
 545  E :      PEFileStructPtr<DWORD> name;
 546  E :      if (!name.Set(export_dir_block,
 547    :                    RelativeAddress(export_dir->AddressOfNames))) {
 548  i :        LOG(ERROR) << "Unable to parse export name table.";
 549    :      }
 550    :  
 551  E :      for (size_t i = 0; i < export_dir->NumberOfNames; ++i) {
 552    :        // All the names in the export directory should point back into
 553    :        // the export directory, sanity check this.
 554  E :        DCHECK_EQ(export_dir_block, address_space_->GetContainingBlock(
 555    :            RelativeAddress(*name.ptr()),
 556  E :            sizeof(RelativeAddress)));
 557    :  
 558  E :        if (!AddRelative(name, name.ptr())) {
 559  i :          LOG(ERROR) << "Unable to add reference to export function name.";
 560  i :          return NULL;
 561    :        }
 562    :  
 563  E :        if (!name.Next()) {
 564  i :          LOG(ERROR) << "Unable to parse export function table.";
 565  i :          return NULL;
 566    :        }
 567  E :      }
 568    :    }
 569    :  
 570  E :    if (export_dir->AddressOfNameOrdinals != 0) {
 571  E :      DCHECK_EQ(export_dir_block, address_space_->GetContainingBlock(
 572    :          RelativeAddress(export_dir->AddressOfNameOrdinals),
 573  E :          sizeof(RelativeAddress)));
 574  E :      if (!AddRelative(export_dir, &export_dir->AddressOfNameOrdinals)) {
 575  i :        LOG(ERROR) << "Unable to add export address of ordinals reference.";
 576  i :        return NULL;
 577    :      }
 578    :    }
 579    :  
 580  E :    return export_dir_block;
 581  E :  }
 582    :  
 583  E :  size_t PEFileParser::CountImportThunks(RelativeAddress thunk_start) {
 584  E :    size_t num_thunks = 0;
 585  E :    for (; true; ++num_thunks, thunk_start += sizeof(IMAGE_THUNK_DATA)) {
 586  E :      PEFileStructPtr<IMAGE_THUNK_DATA> thunk;
 587  E :      if (!thunk.Read(image_file_, thunk_start)) {
 588    :        // We didn't get to the sentinel, that's an error.
 589  i :        LOG(ERROR) << "Unable to read image import thunk.";
 590  i :        return 0;
 591    :      }
 592    :  
 593  E :      if (thunk->u1.AddressOfData == 0U)
 594  E :        break;
 595  E :    }
 596    :  
 597  E :    return num_thunks;
 598  E :  }
 599    :  
 600    :  bool PEFileParser::ParseImportThunks(RelativeAddress thunk_start,
 601    :                                       size_t num_thunks,
 602    :                                       bool is_bound,
 603    :                                       ThunkTableType table_type,
 604    :                                       const char* thunk_type,
 605  E :                                       const char* import_name) {
 606    :    // Only certain table types may be bound.
 607  E :    DCHECK(!is_bound || table_type == kImportAddressTable ||
 608    :               table_type == kDelayLoadBoundImportAddressTable);
 609    :  
 610    :    // Start by chunking the IAT/INT, including the terminating sentinel.
 611  E :    size_t ixt_size = sizeof(IMAGE_THUNK_DATA) * (num_thunks + 1);
 612    :  
 613    :    std::string ixt_name =
 614  E :        base::StringPrintf("%s for \"%s\"", thunk_type, import_name);
 615    :  
 616  E :    BlockGraph::Block* thunk_block = NULL;
 617  E :    if (table_type == kDelayLoadBoundImportAddressTable) {
 618  E :      thunk_block = ChunkDelayBoundIATBlock(thunk_start, ixt_size,
 619    :                                            ixt_name.c_str());
 620  E :    } else {
 621    :      // Try to add the block.
 622  E :      thunk_block = AddBlock(BlockGraph::DATA_BLOCK,
 623    :                             thunk_start,
 624    :                             ixt_size,
 625    :                             ixt_name.c_str());
 626    :  
 627    :      // The IAT may have been chunked while parsing the IAT data directory,
 628    :      // in which case we want to leave a label for the start of our entries. In
 629    :      // this case we should be wholly contained in an existing block.
 630  E :      if (thunk_block == NULL)
 631  E :        thunk_block = address_space_->GetContainingBlock(thunk_start, ixt_size);
 632    :    }
 633    :  
 634  E :    if (thunk_block == NULL) {
 635  i :      LOG(ERROR) << "Unable to add " << thunk_type
 636    :                 << "block for " << import_name;
 637  i :      return false;
 638    :    }
 639    :  
 640    :    // Add a label to the start of the table.
 641  E :    thunk_block->SetLabel(thunk_start - thunk_block->addr(),
 642    :                          ixt_name,
 643    :                          BlockGraph::DATA_LABEL);
 644    :  
 645    :    // Determine the type of data in the table. We only chunk out names for
 646    :    // import name tables. This prevents us from doing the work twice for an
 647    :    // unbound IAT.
 648  E :    ThunkDataType thunk_data_type = GetThunkDataType(table_type, is_bound);
 649  E :    bool chunk_names = table_type == kImportNameTable ||
 650    :        table_type == kDelayLoadImportNameTable;
 651    :  
 652    :    // Run through and validate the table contents, parsing IMAGE_IMPORT_BY_NAMES
 653    :    // if we're in an import name table.
 654  E :    for (size_t i = 0; i < num_thunks; ++i) {
 655  E :      if (!ParseImportThunk(thunk_start, thunk_data_type, thunk_type,
 656    :                            import_name, chunk_names)) {
 657  i :        return false;
 658    :      }
 659  E :      thunk_start += sizeof(IMAGE_THUNK_DATA);
 660  E :    }
 661    :  
 662  E :    return true;
 663  E :  }
 664    :  
 665    :  bool PEFileParser::ParseImportThunk(RelativeAddress thunk_addr,
 666    :                                      ThunkDataType thunk_data_type,
 667    :                                      const char* thunk_type,
 668    :                                      const char* module_name,
 669  E :                                      bool chunk_name) {
 670    :    // We can only chunk names if we're parsing an IMAGE_THUNK_DATA object.
 671  E :    DCHECK(!chunk_name || thunk_data_type == kImageThunkData);
 672    :  
 673  E :    PEFileStructPtr<IMAGE_THUNK_DATA> thunk;
 674  E :    if (!thunk.Read(image_file_, thunk_addr)) {
 675  i :      LOG(ERROR) << "Unable to read image import thunk.";
 676  i :      return false;
 677    :    }
 678    :  
 679  E :    switch (thunk_data_type) {
 680    :      case kNullThunkData: {
 681  i :        if (thunk->u1.AddressOfData != 0) {
 682  i :          LOG(ERROR) << "Expect NULL " << thunk_type << " thunk, got 0x"
 683    :                     << std::hex << thunk->u1.AddressOfData;
 684  i :          return false;
 685    :        }
 686  i :        break;
 687    :      }
 688    :  
 689    :      case kImageThunkData: {
 690    :        // If it's an ordinal, there's nothing to do.
 691  E :        if (IMAGE_SNAP_BY_ORDINAL(thunk->u1.Ordinal))
 692  E :          break;
 693    :  
 694    :        // It's not an ordinal, so it must contain an RVA to an
 695    :        // IMAGE_IMPORT_BY_NAME.
 696    :  
 697    :        // Add the IAT/INT->thunk reference.
 698    :        // Assuming little endian representation.
 699  E :        if (!AddRelative(thunk, reinterpret_cast<const DWORD*>(
 700    :            &thunk->u1.AddressOfData))) {
 701  i :          LOG(ERROR) << "Unable to add import thunk reference.";
 702  i :          return false;
 703    :        }
 704    :  
 705    :        // Read the thunk and name & chunk it out.
 706  E :        PEFileStructPtr<IMAGE_IMPORT_BY_NAME> name_thunk;
 707  E :        RelativeAddress name_thunk_addr(thunk->u1.AddressOfData);
 708  E :        if (!name_thunk.Read(image_file_, name_thunk_addr)) {
 709  i :          LOG(ERROR) << "Unable to read import name thunk.";
 710  i :          return false;
 711    :        }
 712    :  
 713  E :        std::string function_name;
 714    :        RelativeAddress function_name_addr(
 715  E :            name_thunk.AddressOf(&name_thunk->Name));
 716  E :        if (!image_file_.ReadImageString(function_name_addr, &function_name)) {
 717  i :          LOG(ERROR) << "Unable to read import function name.";
 718  i :          return false;
 719    :        }
 720    :  
 721    :        // Calculate the even-padded size of the name thunk.
 722  E :        size_t name_thunk_size = common::AlignUp(
 723    :            offsetof(IMAGE_IMPORT_BY_NAME, Name) + function_name.size() + 1, 2);
 724    :  
 725    :        // Chunk the names only on request, as more than one IAT/INT may
 726    :        // point to the same name blocks.
 727  E :        if (chunk_name) {
 728  E :          BlockGraph::Block* thunk = AddBlock(
 729    :              BlockGraph::DATA_BLOCK,
 730    :              name_thunk_addr,
 731    :              name_thunk_size,
 732    :              base::StringPrintf("Import Name Thunk \"%s\" from \"%s\"",
 733    :                                 function_name.c_str(),
 734    :                                 module_name).c_str());
 735  E :          if (thunk == NULL) {
 736  i :            LOG(ERROR) << "Unable to add function name block.";
 737  i :            return false;
 738    :          }
 739    :  
 740  E :          if (!on_import_thunk_.Run(module_name, function_name.c_str(), thunk)) {
 741  i :            LOG(ERROR) << "OnImportThunk callback failed.";
 742  i :            return false;
 743    :          }
 744  E :        } else {
 745    :  #ifndef NDEBUG
 746    :          // Check that the name blocks exist in debug.
 747    :          BlockGraph::Block* block =
 748  E :              address_space_->GetBlockByAddress(name_thunk_addr);
 749  E :          DCHECK(block != NULL);
 750  E :          DCHECK_EQ(name_thunk_size, block->size());
 751    :  #endif  // NDEBUG
 752    :        }
 753  E :        break;
 754  i :      }
 755    :  
 756    :      case kCodeInImageThunkData: {
 757    :        // Add the code reference. This will check that it is in fact a reference
 758    :        // to an address in the image, and track the associated block
 759    :        // automatically.
 760    :        // Assuming little endian representation.
 761  E :        if (!AddAbsolute(thunk, reinterpret_cast<const DWORD*>(
 762    :            &thunk->u1.AddressOfData))) {
 763  i :          LOG(ERROR) << "Unable to add import thunk reference.";
 764  i :          return false;
 765    :        }
 766  E :        break;
 767    :      }
 768    :  
 769    :      case kCodeOutOfImageThunkData: {
 770    :        // This is an absolute address to code outside of the image. It may
 771    :        // actually have an address that lies inside our image because the
 772    :        // imported module may have an overlapping preferred load address.
 773  i :        if (thunk->u1.AddressOfData < 0x1000) {
 774  i :          AbsoluteAddress abs_addr(thunk->u1.AddressOfData);
 775  i :          LOG(ERROR) << thunk_type << " thunk to external code has invalid "
 776    :                     << "address: " << abs_addr;
 777  i :          return false;
 778    :        }
 779    :        break;
 780    :      }
 781    :  
 782    :      case kArbitraryThunkData: {
 783    :        // We do nothing. Anything goes!
 784    :        break;
 785    :      }
 786    :    }
 787    :  
 788  E :    return true;
 789  E :  }
 790    :  
 791    :  BlockGraph::Block* PEFileParser::ChunkDelayBoundIATBlock(
 792  E :      RelativeAddress iat_addr, size_t iat_size, const char* iat_name) {
 793  E :    BlockGraph::Block* iat_block = AddBlock(BlockGraph::DATA_BLOCK,
 794    :                                            iat_addr,
 795    :                                            iat_size,
 796    :                                            iat_name);
 797  E :    if (iat_block != NULL)
 798  E :      return iat_block;
 799    :  
 800    :    // If we get here we were unable to create a block, so there must be a
 801    :    // conflict. We've seen the bound IATs for delay-loaded libraries be too
 802    :    // small. That is, one library's bound IAT is overwritten by another library's
 803    :    // bound IAT. We do our best to patch things up, by growing the conflicting
 804    :    // pre-existing block to also cover the range of the block we want to create.
 805    :    //
 806    :    // We extend the existing block by creating new blocks (one to the left, one
 807    :    // to the right) of the conflicting block that cover the portion of the new
 808    :    // table that is not covered. Then, we merge them all.
 809    :  
 810  i :    iat_block = address_space_->GetFirstIntersectingBlock(iat_addr,
 811    :                                                          iat_size);
 812  i :    VLOG(1) << iat_name << " collides with existing block " << iat_block->name()
 813    :            << ".";
 814    :  
 815    :    // If we're completely contained within the conflicting block, there's no
 816    :    // expanding and merging to do.
 817  i :    if (iat_block->Contains(iat_addr, iat_size))
 818  i :      return iat_block;
 819    :  
 820    :    // Create a block to the left of the existing block, if the desired table
 821    :    // extends to the left.
 822  i :    if (iat_addr < iat_block->addr()) {
 823  i :      size_t pre_size = iat_block->addr() - iat_addr;
 824  i :      BlockGraph::Block* pre_block = AddBlock(BlockGraph::DATA_BLOCK,
 825    :                                              iat_addr,
 826    :                                              pre_size,
 827    :                                              iat_name);
 828    :      // This should never fail as iat_block is the *first* intersecting
 829    :      // block.
 830  i :      DCHECK(pre_block != NULL);
 831    :    }
 832    :  
 833    :    // Insert the missing part of this table to the right of the intersecting
 834    :    // block, if there is any needed.
 835  i :    RelativeAddress new_end = iat_addr + iat_size;
 836  i :    RelativeAddress old_end = iat_block->addr() + iat_block->size();
 837  i :    if (new_end > old_end) {
 838    :      BlockGraph::Block* next_block =
 839  i :          address_space_->GetFirstIntersectingBlock(
 840    :              old_end, new_end - old_end);
 841    :  
 842  i :      if (next_block != NULL)
 843  i :        new_end = next_block->addr();
 844    :  
 845  i :      if (new_end > old_end) {
 846  i :        BlockGraph::Block* post_block = AddBlock(BlockGraph::DATA_BLOCK,
 847    :                                                 old_end,
 848    :                                                 new_end - old_end,
 849    :                                                 NULL);
 850    :        // This should never fail as we're inserting after the end of
 851    :        // iat_block, and before the start of the next block in the
 852    :        // address space.
 853  i :        DCHECK(post_block != NULL);
 854    :      }
 855    :    }
 856    :  
 857    :    // Merge the blocks to create one new contiguous block.
 858  i :    BlockGraph::AddressSpace::Range range(iat_addr, iat_size);
 859  i :    if (!address_space_->MergeIntersectingBlocks(range)) {
 860  i :      LOG(ERROR) << "Unable to merge intersecting bound IAT blocks.";
 861  i :      return NULL;
 862    :    }
 863  i :    iat_block = address_space_->GetContainingBlock(iat_addr, iat_size);
 864  i :    DCHECK(iat_block != NULL);
 865    :  
 866  i :    return iat_block;
 867  E :  }
 868    :  
 869    :  BlockGraph::Block* PEFileParser::ParseImportDir(
 870  E :      const IMAGE_DATA_DIRECTORY& dir) {
 871    :    // Read the import descriptor, we're going to iterate it.
 872  E :    RelativeAddress import_descriptor_addr(dir.VirtualAddress);
 873  E :    PEFileStructPtr<IMAGE_IMPORT_DESCRIPTOR> import_descriptor;
 874  E :    if (!import_descriptor.Read(image_file_,
 875    :                                import_descriptor_addr,
 876    :                                dir.Size)) {
 877  i :      LOG(ERROR) << "Unable to read the import directory.";
 878  i :      return NULL;
 879    :    }
 880    :  
 881    :    do {
 882    :      // The last import descriptor is a sentinel.
 883  E :      if (import_descriptor->Characteristics == 0) {
 884  E :        DCHECK_EQ(0U, import_descriptor->Name);
 885  E :        DCHECK_EQ(0U, import_descriptor->FirstThunk);
 886  E :        break;
 887    :      }
 888    :  
 889    :      // Read the name of the imported DLL.
 890  E :      std::string import_name;
 891  E :      RelativeAddress import_name_addr(import_descriptor->Name);
 892  E :      if (!image_file_.ReadImageString(import_name_addr, &import_name)) {
 893  i :        LOG(ERROR) << "Unable to read import name.";
 894  i :        return NULL;
 895    :      }
 896    :  
 897  E :      if (!AddBlock(BlockGraph::DATA_BLOCK,
 898    :                    import_name_addr,
 899    :                    common::AlignUp(import_name.size() + 1, 2),
 900    :                    base::StringPrintf("Import DLL Name \"%s\"",
 901    :                                       import_name.c_str()).c_str())) {
 902  i :        LOG(ERROR) << "Unable to create import name block.";
 903  i :        return NULL;
 904    :      }
 905    :  
 906  E :      if (!AddRelative(import_descriptor, &import_descriptor->Name)) {
 907  i :        LOG(ERROR) << "Unable to add import name reference.";
 908  i :        return NULL;
 909    :      }
 910    :  
 911    :      // Count the number of import name thunks for this import descriptor.
 912    :      RelativeAddress thunk_addr =
 913  E :          RelativeAddress(import_descriptor->OriginalFirstThunk);
 914  E :      size_t num_thunks = CountImportThunks(thunk_addr);
 915  E :      if (num_thunks == 0)
 916  i :        return NULL;
 917    :  
 918    :      // Parse the Import Name Table.
 919  E :      if (!ParseImportThunks(thunk_addr, num_thunks, false,
 920    :                             kImportNameTable, "INT", import_name.c_str())) {
 921  i :        return NULL;
 922    :      }
 923    :  
 924    :      // Parse the Import Address Table.
 925  E :      bool iat_is_bound = import_descriptor->TimeDateStamp != 0;
 926  E :      if (!ParseImportThunks(RelativeAddress(import_descriptor->FirstThunk),
 927    :                             num_thunks, iat_is_bound,
 928    :                             kImportAddressTable, "IAT", import_name.c_str())) {
 929  i :        return NULL;
 930    :      }
 931    :  
 932  E :      if (!AddRelative(import_descriptor,
 933    :                       &import_descriptor->OriginalFirstThunk)) {
 934  i :        LOG(ERROR) << "Unable to add import name table reference.";
 935  i :        return NULL;
 936    :      }
 937    :  
 938  E :      if (!AddRelative(import_descriptor, &import_descriptor->FirstThunk)) {
 939  i :        LOG(ERROR) << "Unable to add import address table reference.";
 940  i :        return NULL;
 941    :      }
 942  E :    } while (import_descriptor.Next());
 943    :  
 944    :    BlockGraph::Block* import_descriptor_block =
 945  E :        AddBlock(BlockGraph::DATA_BLOCK,
 946    :                 import_descriptor_addr,
 947    :                 import_descriptor.addr() - import_descriptor_addr +
 948    :                     sizeof(IMAGE_IMPORT_DESCRIPTOR),
 949    :                 "Import Directory");
 950    :  
 951  E :    return import_descriptor_block;
 952  E :  }
 953    :  
 954    :  BlockGraph::Block *PEFileParser::ParseComDescriptorDir(
 955  i :      const IMAGE_DATA_DIRECTORY &dir) {
 956  i :    LOG(ERROR) << "Parsing for COM descriptors not implemented.";
 957  i :    return NULL;
 958  i :  }
 959    :  
 960    :  BlockGraph::Block *PEFileParser::ParseDelayImportDir(
 961  E :      const IMAGE_DATA_DIRECTORY &dir) {
 962    :    // Read the delay import descriptor, we're going to iterate it.
 963  E :    RelativeAddress import_descriptor_addr(dir.VirtualAddress);
 964  E :    PEFileStructPtr<ImgDelayDescr> import_descriptor;
 965  E :    if (!import_descriptor.Read(image_file_,
 966    :                                import_descriptor_addr,
 967    :                                dir.Size)) {
 968  i :      LOG(ERROR) << "Unable to read the delay import directory.";
 969  i :      return NULL;
 970    :    }
 971    :  
 972    :    do {
 973    :      // The last descriptor is a sentinel.
 974  E :      if (import_descriptor->grAttrs == 0)
 975  E :        break;
 976    :  
 977  E :      if (import_descriptor->grAttrs != dlattrRva) {
 978  i :        LOG(ERROR) << "Unexpected attributes in delay import descriptor 0x"
 979    :                   << std::hex << import_descriptor->grAttrs;
 980  i :        return NULL;
 981    :      }
 982    :  
 983    :      // Read the name of the delay imported DLL.
 984  E :      std::string import_name;
 985  E :      RelativeAddress import_name_addr(import_descriptor->rvaDLLName);
 986  E :      if (!image_file_.ReadImageString(import_name_addr, &import_name)) {
 987  i :        LOG(ERROR) << "Unable to read delay import name.";
 988  i :        return NULL;
 989    :      }
 990    :  
 991  E :      if (!AddBlock(BlockGraph::DATA_BLOCK,
 992    :                    import_name_addr,
 993    :                    common::AlignUp(import_name.size() + 1, 2),
 994    :                    base::StringPrintf("Delay import DLL Name \"%s\"",
 995    :                                       import_name.c_str()).c_str())) {
 996  i :        LOG(ERROR) << "Unable to create import name block.";
 997  i :        return NULL;
 998    :      }
 999    :  
1000  E :      if (!AddRelative(import_descriptor, &import_descriptor->rvaDLLName)) {
1001  i :        LOG(ERROR) << "Unable to add delay import name reference.";
1002  i :        return NULL;
1003    :      }
1004    :  
1005    :      // Chunk the HMODULE for this import.
1006  E :      if (!AddBlock(BlockGraph::DATA_BLOCK,
1007    :                    RelativeAddress(import_descriptor->rvaHmod),
1008    :                    sizeof(HMODULE),
1009    :                    base::StringPrintf("Module handle for delay import DLL\"%s\"",
1010    :                                       import_name.c_str()).c_str())) {
1011  i :        LOG(ERROR) << "Unable to create import module handle block.";
1012  i :        return NULL;
1013    :      }
1014    :  
1015  E :      if (!AddRelative(import_descriptor, &import_descriptor->rvaHmod)) {
1016  i :        LOG(ERROR) << "Unable to delay import module handle reference.";
1017  i :        return NULL;
1018    :      }
1019    :  
1020    :      // Count the number of import name thunks for this import descriptor.
1021  E :      RelativeAddress int_addr(import_descriptor->rvaINT);
1022  E :      size_t num_thunks = CountImportThunks(int_addr);
1023  E :      if (num_thunks == 0)
1024  i :        return NULL;
1025    :  
1026    :      // Parse the Delay Import Name Table.
1027  E :      if (!ParseImportThunks(int_addr, num_thunks, false,
1028    :                             kDelayLoadImportNameTable, "DelayINT",
1029    :                             import_name.c_str())) {
1030  i :        return NULL;
1031    :      }
1032    :  
1033  E :      if (!AddRelative(import_descriptor, &import_descriptor->rvaINT)) {
1034  i :        LOG(ERROR) << "Unable to add delay import name table reference.";
1035  i :        return NULL;
1036    :      }
1037    :  
1038    :      // Parse the Delay Import Address Table.
1039  E :      if (!ParseImportThunks(RelativeAddress(import_descriptor->rvaIAT),
1040    :                             num_thunks, false,
1041    :                             kDelayLoadImportAddressTable, "DelayIAT",
1042    :                             import_name.c_str())) {
1043  i :        return NULL;
1044    :      }
1045    :  
1046  E :      if (!AddRelative(import_descriptor, &import_descriptor->rvaIAT)) {
1047  i :        LOG(ERROR) << "Unable to add delay import address table reference.";
1048  i :        return NULL;
1049    :      }
1050    :  
1051    :      // Parse the Bound Import Address Table.
1052  E :      bool iat_is_bound = import_descriptor->dwTimeStamp != 0;
1053  E :      if (!ParseImportThunks(RelativeAddress(import_descriptor->rvaBoundIAT),
1054    :                             num_thunks, iat_is_bound,
1055    :                             kDelayLoadBoundImportAddressTable, "DelayBoundIAT",
1056    :                             import_name.c_str())) {
1057  i :        return NULL;
1058    :      }
1059    :  
1060  E :      if (!AddRelative(import_descriptor, &import_descriptor->rvaBoundIAT)) {
1061  i :        LOG(ERROR) << "Unable to add delay bound import address table reference.";
1062  i :        return NULL;
1063    :      }
1064    :  
1065  E :      if (import_descriptor->rvaUnloadIAT != 0U) {
1066  i :        LOG(ERROR) << "Unexpected UnloadIAT.";
1067  i :        return NULL;
1068    :      }
1069    :  
1070  E :      if (import_descriptor->dwTimeStamp != 0U) {
1071  i :        LOG(ERROR) << "Unexpected bound delay imports.";
1072  i :        return NULL;
1073    :      }
1074  E :    } while (import_descriptor.Next());
1075    :  
1076    :    BlockGraph::Block* import_descriptor_block =
1077  E :        AddBlock(BlockGraph::DATA_BLOCK,
1078    :                 import_descriptor_addr,
1079    :                 import_descriptor.addr() - import_descriptor_addr +
1080    :                     sizeof(ImgDelayDescr),
1081    :                 "Delay Import Directory");
1082    :  
1083  E :    return import_descriptor_block;
1084  E :  }
1085    :  
1086    :  BlockGraph::Block *PEFileParser::ParseIatDir(
1087  E :      const IMAGE_DATA_DIRECTORY &dir) {
1088  E :    return AddBlock(BlockGraph::DATA_BLOCK,
1089    :                    RelativeAddress(dir.VirtualAddress),
1090    :                    dir.Size,
1091    :                    "Import Address Table");
1092  E :  }
1093    :  
1094    :  BlockGraph::Block *PEFileParser::ParseBoundImportDir(
1095  i :      const IMAGE_DATA_DIRECTORY &dir) {
1096  i :    LOG(ERROR) << "Parsing for bound import dir not implemented.";
1097  i :    return NULL;
1098  i :  }
1099    :  
1100    :  BlockGraph::Block *PEFileParser::ParseGlobalDir(
1101  i :      const IMAGE_DATA_DIRECTORY &dir) {
1102  i :    LOG(ERROR) << "Parsing for global dir not implemented.";
1103  i :    return NULL;
1104  i :  }
1105    :  
1106    :  BlockGraph::Block *PEFileParser::ParseArchitectureDir(
1107  i :      const IMAGE_DATA_DIRECTORY &dir) {
1108  i :    LOG(ERROR) << "Parsing for architecture dir not implemented.";
1109  i :    return NULL;
1110  i :  }
1111    :  
1112    :  BlockGraph::Block *PEFileParser::ParseRelocDir(
1113  E :      const IMAGE_DATA_DIRECTORY &dir) {
1114  E :    return AddBlock(BlockGraph::DATA_BLOCK,
1115    :                    RelativeAddress(dir.VirtualAddress),
1116    :                    dir.Size,
1117    :                    "Relocations");
1118  E :  }
1119    :  
1120    :  BlockGraph::Block *PEFileParser::ParseSecurityDir(
1121  i :      const IMAGE_DATA_DIRECTORY &dir) {
1122  i :    LOG(ERROR) << "Parsing for security dir not implemented.";
1123  i :    return NULL;
1124  i :  }
1125    :  
1126    :  BlockGraph::Block *PEFileParser::ParseExceptionDir(
1127  i :      const IMAGE_DATA_DIRECTORY &dir) {
1128  i :    LOG(ERROR) << "Parsing for exception dir not implemented.";
1129  i :    return NULL;
1130  i :  }
1131    :  
1132    :  BlockGraph::Block* PEFileParser::ParseTlsDir(
1133  E :      const IMAGE_DATA_DIRECTORY& dir) {
1134    :    BlockGraph::Block* tls_directory_block =
1135  E :        AddBlock(BlockGraph::DATA_BLOCK,
1136    :                 RelativeAddress(dir.VirtualAddress),
1137    :                 sizeof(IMAGE_TLS_DIRECTORY),
1138    :                 "Tls Directory");
1139  E :    if (tls_directory_block == NULL)
1140  i :      return NULL;
1141    :  
1142  E :    PEFileStructPtr<IMAGE_TLS_DIRECTORY> tls_directory;
1143  E :    if (!tls_directory.Set(tls_directory_block)) {
1144  i :      LOG(ERROR) << "Unable to read the TLS directory.";
1145  i :      return NULL;
1146    :    }
1147    :  
1148  E :    return tls_directory_block;
1149  E :  }
1150    :  
1151    :  BlockGraph::Block* PEFileParser::ParseLoadConfigDir(
1152  E :      const IMAGE_DATA_DIRECTORY& dir) {
1153    :    // The load config directory starts with a size field, which we use as the
1154    :    // size for chunking. It appears the size of the data directory entry is
1155    :    // always fixed, but the structure itself has grown over time.
1156  E :    PEFileStructPtr<DWORD> load_config_len;
1157  E :    if (!load_config_len.Read(image_file_, RelativeAddress(dir.VirtualAddress))) {
1158  i :      LOG(ERROR) << "Unable to read load config len.";
1159  i :      return NULL;
1160    :    }
1161    :  
1162    :    LoadConfigDirectoryVersion load_config_version =
1163  E :        kLoadConfigDirectorySizeUnknown;
1164  E :    switch (*load_config_len.ptr()) {
1165    :      case kLoadConfigDirectorySize80:
1166    :      case kLoadConfigDirectorySize81:
1167  E :        load_config_version =
1168    :            static_cast<LoadConfigDirectoryVersion>(*load_config_len.ptr());
1169  E :        break;
1170    :      default:
1171  i :        LOG(ERROR) << "Unknown version of the IMAGE_LOAD_CONFIG_DIRECTORY "
1172    :                   << "structure (" << *load_config_len.ptr() << " bytes), might "
1173    :                   << "be because you're using a new version of the Windows SDK.";
1174  i :        return NULL;
1175    :    }
1176    :  
1177    :    BlockGraph::Block* load_config_block =
1178  E :        AddBlock(BlockGraph::DATA_BLOCK,
1179    :                 RelativeAddress(dir.VirtualAddress),
1180    :                 *load_config_len.ptr(),
1181    :                 "Load Config Directory");
1182    :  
1183  E :    DCHECK_NE(static_cast<BlockGraph::Block*>(nullptr), load_config_block);
1184    :  
1185    :    // Use SetUnchecked here as the load config structure may be longer than the
1186    :    // data we have for it.
1187  E :    PEFileStructPtr<LoadConfigDirectory> load_config;
1188  E :    if (!load_config.SetUnchecked(load_config_block)) {
1189  i :      LOG(ERROR) << "Unable to parse the load config directory.";
1190  i :      return NULL;
1191    :    }
1192    :  
1193    :    // TODO(siggi): Must length check prior to each of these...
1194    :    if (!AddAbsolute(load_config, &load_config->LockPrefixTable) ||
1195    :        !AddAbsolute(load_config, &load_config->EditList) ||
1196    :        !AddAbsolute(load_config, &load_config->SecurityCookie) ||
1197    :        !AddAbsolute(load_config, &load_config->SEHandlerTable) ||
1198    :        !MaybeAddAbsolute(load_config,
1199  E :                          &load_config->GuardCFCheckFunctionPointer) ||
1200    :        !MaybeAddAbsolute(load_config, &load_config->GuardCFFunctionTable)) {
1201  i :      LOG(ERROR) << "Unable to add load config directory references.";
1202  i :      return NULL;
1203    :    }
1204    :  
1205    :    // Iterate the exception handlers and add references for them.
1206  E :    RelativeAddress seh_handler;
1207  E :    PEFileStructPtr<DWORD> seh_handlers;
1208    :    if (!image_file_.Translate(AbsoluteAddress(load_config->SEHandlerTable),
1209  E :                               &seh_handler) ||
1210    :        !seh_handlers.Read(image_file_, seh_handler,
1211    :                           load_config->SEHandlerCount * sizeof(DWORD))) {
1212  i :      LOG(ERROR) << "Unable to read SEH handler table.";
1213  i :      return NULL;
1214    :    }
1215    :  
1216  E :    for (size_t i = 0; i < load_config->SEHandlerCount; ++i) {
1217  E :      if (!AddRelative(seh_handlers, seh_handlers.ptr() + i)) {
1218  i :        LOG(ERROR) << "Unable to add SEH handler reference.";
1219  i :        return NULL;
1220    :      }
1221  E :    }
1222    :  
1223    :    // TODO(siggi): Add new load config directory fields.
1224    :    // As of WDK 8.1 we have the following new fields:
1225    :    // DWORD   GuardCFCheckFunctionPointer;    // VA
1226    :    // DWORD   Reserved2;
1227    :    // DWORD   GuardCFFunctionTable;           // VA
1228    :    // DWORD   GuardCFFunctionCount;
1229    :    // DWORD   GuardFlags;
1230    :  
1231  E :    return load_config_block;
1232  E :  }
1233    :  
1234    :  BlockGraph::Block* PEFileParser::ParseDebugDir(
1235  E :      const IMAGE_DATA_DIRECTORY& dir) {
1236    :    BlockGraph::Block* debug_directory_block =
1237  E :        AddBlock(BlockGraph::DATA_BLOCK,
1238    :                 RelativeAddress(dir.VirtualAddress),
1239    :                 dir.Size,
1240    :                 "Debug Directory");
1241  E :    if (debug_directory_block == NULL)
1242  i :      return NULL;
1243    :  
1244  E :    PEFileStructPtr<IMAGE_DEBUG_DIRECTORY> debug_directory;
1245  E :    if (!debug_directory.Set(debug_directory_block)) {
1246  i :      LOG(ERROR) << "Unable to read the debug directory.";
1247  i :      return NULL;
1248    :    }
1249    :  
1250    :    do {
1251  E :      if (!AddRelative(debug_directory, &debug_directory->AddressOfRawData) ||
1252    :          !AddFileOffset(debug_directory, &debug_directory->PointerToRawData)) {
1253  i :        LOG(ERROR) << "Failed to add debug directory references.";
1254  i :        return NULL;
1255    :      }
1256    :  
1257    :      // Don't create a block for empty directories. This is seen with VS2015
1258    :      // Incremental Link Time Code Generation, which generates an empty "iltcg"
1259    :      // debug directory entry.
1260  E :      if (debug_directory->SizeOfData == 0)
1261  E :        continue;
1262    :  
1263    :      // Chunk the data referenced by the debug directory entry.
1264  E :      AddBlock(BlockGraph::DATA_BLOCK,
1265    :               RelativeAddress(debug_directory->AddressOfRawData),
1266    :               debug_directory->SizeOfData, "Debug Info");
1267  E :    } while (debug_directory.Next());
1268    :  
1269  E :    return debug_directory_block;
1270  E :  }
1271    :  
1272    :  BlockGraph::Block* PEFileParser::ParseResourceDir(
1273  E :      const IMAGE_DATA_DIRECTORY& dir) {
1274    :    BlockGraph::Block* resource_block =
1275  E :        AddBlock(BlockGraph::DATA_BLOCK,
1276    :                 RelativeAddress(dir.VirtualAddress),
1277    :                 dir.Size,
1278    :                 "Resource Directory");
1279  E :    if (resource_block == NULL)
1280  i :      return NULL;
1281    :  
1282  E :    if (!ParseResourceDirImpl(resource_block, 0))
1283  i :      return NULL;
1284    :  
1285  E :    return resource_block;
1286  E :  }
1287    :  
1288    :  bool PEFileParser::ParseResourceDirImpl(BlockGraph::Block* resource_block,
1289  E :                                          size_t root_offset) {
1290  E :    DCHECK(resource_block != NULL);
1291  E :    RelativeAddress root_addr = resource_block->addr();
1292    :  
1293    :    // Setup the directory node we're currently scanning.
1294  E :    PEFileStructPtr<IMAGE_RESOURCE_DIRECTORY> directory;
1295  E :    if (!directory.Set(resource_block, root_addr + root_offset)) {
1296  i :      LOG(ERROR) << "Unable to read the resource directory.";
1297  i :      return false;
1298    :    }
1299    :  
1300    :    // How many entries hang from this node in the resource tree?
1301  E :    size_t num_entries = directory->NumberOfNamedEntries +
1302    :        directory->NumberOfIdEntries;
1303  E :    size_t entry_offset = root_offset + sizeof(IMAGE_RESOURCE_DIRECTORY);
1304    :  
1305    :    // Let's walk through them.
1306  E :    for (size_t i = 0; i < num_entries; ++i) {
1307    :      // Note that the offsets in the directory entries are all relative to
1308    :      // the root address of the resource block.
1309  E :      PEFileStructPtr<IMAGE_RESOURCE_DIRECTORY_ENTRY> directory_entry;
1310  E :      if (!directory_entry.Set(resource_block, root_addr + entry_offset)) {
1311  i :        LOG(ERROR) << "Unable to read the resource directory entry.";
1312  i :        return false;
1313    :      }
1314  E :      if (directory_entry->DataIsDirectory) {
1315  E :        if (!ParseResourceDirImpl(resource_block,
1316    :                                  directory_entry->OffsetToDirectory)) {
1317  i :          return false;
1318    :        }
1319  E :      } else {
1320  E :        PEFileStructPtr<IMAGE_RESOURCE_DATA_ENTRY> data_entry;
1321  E :        RelativeAddress entry_addr(root_addr + directory_entry->OffsetToData);
1322  E :        if (!data_entry.Set(resource_block, entry_addr)) {
1323  i :          LOG(ERROR) << "Unable to read the resource data entry.";
1324  i :          return false;
1325    :        }
1326    :        // The offsets in the data entries are RVAs.
1327  E :        if (!AddRelative(data_entry, &data_entry->OffsetToData)) {
1328  i :          LOG(ERROR) << "Failed to add resouce data reference.";
1329  i :          return false;
1330    :        }
1331    :      }
1332  E :      entry_offset += sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY);
1333  E :    }
1334    :  
1335  E :    return true;
1336  E :  }
1337    :  
1338    :  bool PEFileParser::AddReference(RelativeAddress src,
1339    :                                  BlockGraph::ReferenceType type,
1340    :                                  BlockGraph::Size size,
1341  E :                                  RelativeAddress dst) {
1342  E :    return add_reference_.Run(src, type, size, dst);
1343  E :  }
1344    :  
1345    :  BlockGraph::Block* PEFileParser::AddBlock(BlockGraph::BlockType type,
1346    :                                            RelativeAddress addr,
1347    :                                            BlockGraph::Size size,
1348  E :                                            const char* name) {
1349  E :    BlockGraph::Block* block = address_space_->AddBlock(type, addr, size, name);
1350  E :    if (block != NULL) {
1351  E :      block->set_attribute(BlockGraph::PE_PARSED);
1352    :  
1353    :      // Mark the source range from whence this block originates.
1354  E :      bool pushed = block->source_ranges().Push(
1355    :          BlockGraph::Block::DataRange(0, size),
1356    :          BlockGraph::Block::SourceRange(addr, size));
1357  E :      DCHECK(pushed);
1358    :  
1359    :      // Set the section for this block. We let blocks that belong to the header
1360    :      // be marked with kInvalidSectionId.
1361  E :      size_t section = image_file_.GetSectionIndex(addr, size);
1362  E :      if (section == BlockGraph::kInvalidSectionId) {
1363    :        // If no section was found for this block, we expect it to be a part of
1364    :        // the header.
1365  E :        const RelativeAddress end_of_headers(
1366    :            image_file_.nt_headers()->OptionalHeader.SizeOfHeaders);
1367  E :        if (addr + size > end_of_headers) {
1368  i :          LOG(ERROR) << "Found a non-header block outside of sections.";
1369  i :          return NULL;
1370    :        }
1371    :      }
1372  E :      block->set_section(section);
1373    :  
1374  E :      const uint8_t* data = image_file_.GetImageData(addr, size);
1375  E :      if (data != NULL)
1376  E :        block->SetData(data, size);
1377    :    }
1378    :  
1379  E :    return block;
1380  E :  }
1381    :  
1382    :  template <typename ItemType>
1383    :  bool PEFileParser::AddRelative(const PEFileStructPtr<ItemType>& structure,
1384  E :                                 const DWORD* item) {
1385  E :    DCHECK(item != NULL);
1386  E :    if (*item == 0)
1387  E :      return true;
1388    :  
1389  E :    return AddReference(structure.AddressOf(item),
1390    :                        BlockGraph::RELATIVE_REF,
1391    :                        sizeof(*item),
1392    :                        RelativeAddress(*item));
1393  E :  }
1394    :  
1395    :  template <typename ItemType>
1396    :  bool PEFileParser::AddAbsolute(const PEFileStructPtr<ItemType>& structure,
1397  E :                                 const DWORD* item) {
1398  E :    DCHECK(item != NULL);
1399  E :    if (*item == 0)
1400  E :      return true;
1401    :  
1402  E :    AbsoluteAddress abs(*item);
1403  E :    RelativeAddress rel;
1404    :  
1405    :    // We expect item to be the direct (0 offset) absolute address of the
1406    :    // in-image file structure. So, translation to an in-image relative
1407    :    // address is expected to yield a valid RVA.
1408  E :    return image_file_.Translate(abs, &rel) &&
1409    :        AddReference(structure.AddressOf(item),
1410    :                     BlockGraph::ABSOLUTE_REF,
1411    :                     sizeof(*item),
1412    :                     rel);
1413  E :  }
1414    :  
1415    :  template <typename ItemType>
1416    :  bool PEFileParser::MaybeAddAbsolute(const PEFileStructPtr<ItemType>& structure,
1417  E :                                      const DWORD* item) {
1418  E :    DCHECK(item != NULL);
1419    :  
1420  E :    const uint8_t* tmp = reinterpret_cast<const uint8_t*>(item);
1421    :    size_t offset =
1422  E :        tmp - reinterpret_cast<const uint8_t*>(structure.ptr()) + sizeof(*item);
1423  E :    if (structure.len() <= offset)
1424  E :      return true;
1425    :  
1426  E :    return AddAbsolute(structure, item);
1427  E :  }
1428    :  
1429    :  template <typename ItemType>
1430    :  bool PEFileParser::AddFileOffset(const PEFileStructPtr<ItemType>& structure,
1431  E :                                   const DWORD* item) {
1432  E :    DCHECK(item != NULL);
1433  E :    if (*item == 0)
1434  E :      return true;
1435    :  
1436  E :    FileOffsetAddress offs(*item);
1437  E :    RelativeAddress rel;
1438    :  
1439    :    // We expect item to be the direct (0 offset) file offset address of the
1440    :    // in-image file structure. So, translation to an in-image relative
1441    :    // address is expected to yield a valid RVA.
1442  E :    return image_file_.Translate(offs, &rel) &&
1443    :        AddReference(structure.AddressOf(item),
1444    :                     BlockGraph::FILE_OFFSET_REF,
1445    :                     sizeof(*item),
1446    :                     rel);
1447  E :  }
1448    :  
1449    :  }  // namespace pe

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