Coverage for /Syzygy/pe/coff_image_layout_builder.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
79.0%2262860.C++source

Line-by-line coverage:

   1    :  // Copyright 2013 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    :  // The COFF image layout builder does a lot of things (maybe too much for
  16    :  // its own good):
  17    :  // - Assign an address to each block.
  18    :  // - Create and add a relocation block for each section, and remove old ones.
  19    :  // - Fix file offset pointers in section contents, headers, and tables.
  20    :  //
  21    :  // Since these tasks are very dependent on internals of COFF, which are
  22    :  // missing from our intermediate representation (the block graph and
  23    :  // associated metadata), they must rely on additional data structures and
  24    :  // book-keeping. Hence they are all collected in this single step instead
  25    :  // of existing as distinct transforms.
  26    :  //
  27    :  // New relocation blocks need to be bound to specific sections, and that
  28    :  // link is not represented in the section info we have in the block
  29    :  // graph. It is probably not useful there as it would only be needed during
  30    :  // patching of COFF headers, and useless with PE.
  31    :  //
  32    :  // Old relocation block removal could be done in a separate transform, but
  33    :  // is image-layout-dependent and hence does not classify as a block graph
  34    :  // transform.
  35    :  //
  36    :  // Fixing references could alternatively be done in the file writer. Most
  37    :  // header fields need to be patched (or their reference updated) during
  38    :  // image laying out, though. Also, relocation references need to be handled
  39    :  // with the creation of the new relocation tables (and do not require
  40    :  // patching). Here we choose to handle all references in the image layout
  41    :  // builder instead of spreading the task across classes.
  42    :  
  43    :  #include "syzygy/pe/coff_image_layout_builder.h"
  44    :  
  45    :  #include <vector>
  46    :  
  47    :  #include "base/auto_reset.h"
  48    :  #include "base/strings/string_util.h"
  49    :  #include "syzygy/block_graph/typed_block.h"
  50    :  #include "syzygy/common/align.h"
  51    :  #include "syzygy/pe/coff_utils.h"
  52    :  #include "syzygy/pe/pe_utils.h"
  53    :  
  54    :  namespace pe {
  55    :  namespace {
  56    :  
  57    :  using block_graph::BlockGraph;
  58    :  using block_graph::ConstTypedBlock;
  59    :  using block_graph::OrderedBlockGraph;
  60    :  using block_graph::TypedBlock;
  61    :  using core::FileOffsetAddress;
  62    :  
  63    :  // A temporary vector holding relocation entries, while building new
  64    :  // relocation blocks.
  65    :  typedef std::vector<IMAGE_RELOCATION> RelocVector;
  66    :  
  67    :  // A map from references to symbol indexes, in order to translate references
  68    :  // to relocations, which are symbol-based.
  69    :  typedef std::map<std::pair<BlockGraph::Block*, BlockGraph::Offset>, size_t>
  70    :      SymbolMap;
  71    :  
  72    :  // A map from section IDs to their (new) position in the resulting layout.
  73    :  typedef std::map<BlockGraph::SectionId, size_t> SectionIndexMap;
  74    :  
  75    :  // Microsoft specifications recommend 4-byte alignment for object files.
  76    :  const size_t kFileAlignment = 4;
  77    :  
  78    :  // The name of the new relocation blocks, generated from references.
  79    :  const char kNewRelocsBlockName[] = "<refs>";
  80    :  
  81    :  // Retrieve the COFF relocation type corresponding to the specified
  82    :  // reference type and size.
  83    :  //
  84    :  // @param ref_type the reference type.
  85    :  // @param ref_size the reference size.
  86    :  // @param coff_reloc_type where to put the resulting COFF relocation type.
  87    :  // @returns true on success, false on failure.
  88    :  bool GetCoffRelocationType(BlockGraph::ReferenceType ref_type,
  89    :                             BlockGraph::Size ref_size,
  90  E :                             uint16* coff_reloc_type) {
  91  E :    switch (ref_type) {
  92    :      case BlockGraph::RELOC_ABSOLUTE_REF:
  93  E :        DCHECK_EQ(sizeof(uint32), ref_size);
  94  E :        *coff_reloc_type = IMAGE_REL_I386_DIR32;
  95  E :        return true;
  96    :      case BlockGraph::RELOC_RELATIVE_REF:
  97  E :        DCHECK_EQ(sizeof(uint32), ref_size);
  98  E :        *coff_reloc_type = IMAGE_REL_I386_DIR32NB;
  99  E :        return true;
 100    :      case BlockGraph::RELOC_SECTION_REF:
 101  E :        DCHECK_EQ(sizeof(uint16), ref_size);
 102  E :        *coff_reloc_type = IMAGE_REL_I386_SECTION;
 103  E :        return true;
 104    :      case BlockGraph::RELOC_SECTION_OFFSET_REF:
 105  E :        if (ref_size == sizeof(uint32)) {
 106  E :           *coff_reloc_type = IMAGE_REL_I386_SECREL;
 107  E :        } else {
 108  i :          DCHECK_EQ(1u, ref_size);
 109  i :          *coff_reloc_type = IMAGE_REL_I386_SECREL7;
 110    :        }
 111  E :        return true;
 112    :      case BlockGraph::RELOC_PC_RELATIVE_REF:
 113  E :        DCHECK_EQ(sizeof(uint32), ref_size);
 114  E :        *coff_reloc_type = IMAGE_REL_I386_REL32;
 115  E :        return true;
 116    :      default:
 117  i :        LOG(ERROR) << "Unexpected reference type.";
 118  i :        return false;
 119    :    }
 120  E :  }
 121    :  
 122    :  // Write a reference value at the specified location. Write the full value
 123    :  // for non-relocation references, or the additional offset only for
 124    :  // relocation references.
 125    :  //
 126    :  // @tparam ValueType the type of data to write.
 127    :  // @param ref the reference to write.
 128    :  // @param block_offset the offset within @p block to alter.
 129    :  // @param block the block to alter.
 130    :  template <typename ValueType>
 131    :  bool WriteReferenceValue(BlockGraph::Reference ref,
 132    :                           BlockGraph::Offset block_offset,
 133  E :                           BlockGraph::Block* block) {
 134  E :    DCHECK_EQ(sizeof(ValueType), ref.size());
 135  E :    TypedBlock<ValueType> value;
 136  E :    if (!value.Init(block_offset, block)) {
 137  i :      LOG(ERROR) << "Unable to cast reference.";
 138  i :      return false;
 139    :    }
 140  E :    if ((ref.type() & BlockGraph::RELOC_REF_BIT) != 0) {
 141  E :      *value = ref.offset() - ref.base();
 142  E :    } else {
 143  E :      *value = ref.offset();
 144    :    }
 145  E :    return true;
 146  E :  }
 147    :  
 148    :  // For each relocation reference in @p block, add a COFF relocation to the
 149    :  // specified vector.
 150    :  //
 151    :  // @param block the block whose references are to be translated to
 152    :  //     relocations.
 153    :  // @param symbol_map the symbol map to use to match references with symbols.
 154    :  // @param relocs vector to which the relocations are to be added.
 155    :  // @returns true on success, false on failure.
 156    :  bool AddRelocs(const BlockGraph::Block& block,
 157    :                 const SymbolMap& symbol_map,
 158  E :                 RelocVector* relocs) {
 159  E :    DCHECK(relocs != NULL);
 160    :  
 161    :    BlockGraph::Block::ReferenceMap::const_iterator it =
 162  E :        block.references().begin();
 163  E :    for (; it != block.references().end(); ++it) {
 164    :      // Skip non-relocation references.
 165  E :      if ((it->second.type() & BlockGraph::RELOC_REF_BIT) == 0)
 166  E :        continue;
 167    :  
 168  E :      IMAGE_RELOCATION reloc = {};
 169    :  
 170    :      // Sections constructed by this class all have zero base RVA, so the
 171    :      // virtual address is just the offset.
 172  E :      reloc.VirtualAddress = it->first;
 173    :  
 174    :      SymbolMap::const_iterator symbol_it =
 175    :          symbol_map.find(std::make_pair(it->second.referenced(),
 176  E :                                         it->second.base()));
 177  E :      if (symbol_it == symbol_map.end()) {
 178  i :        LOG(ERROR) << "Missing COFF symbol for reference within a section block; "
 179    :                   << "cannot translate to relocation.";
 180  i :        return false;
 181    :      }
 182  E :      reloc.SymbolTableIndex = symbol_it->second;
 183    :      if (!GetCoffRelocationType(it->second.type(), it->second.size(),
 184  E :                                 &reloc.Type))
 185  i :        return false;
 186    :  
 187  E :      relocs->push_back(reloc);
 188  E :    }
 189  E :    return true;
 190  E :  }
 191    :  
 192    :  }  // namespace
 193    :  
 194    :  CoffImageLayoutBuilder::CoffImageLayoutBuilder(ImageLayout* image_layout)
 195    :      : PECoffImageLayoutBuilder(image_layout),
 196    :        headers_block_(NULL),
 197    :        symbols_block_(NULL),
 198  E :        strings_block_(NULL) {
 199  E :    PECoffImageLayoutBuilder::Init(kFileAlignment, kFileAlignment);
 200  E :  }
 201    :  
 202    :  bool CoffImageLayoutBuilder::LayoutImage(
 203  E :      const OrderedBlockGraph& ordered_graph) {
 204  E :    DCHECK_EQ(image_layout_->blocks.graph(), ordered_graph.block_graph());
 205    :  
 206  E :    BlockGraph::Block* headers_block = NULL;
 207  E :    BlockGraph::Block* symbols_block = NULL;
 208  E :    BlockGraph::Block* strings_block = NULL;
 209    :  
 210    :    if (!FindCoffSpecialBlocks(image_layout_->blocks.graph(),
 211  E :                               &headers_block, &symbols_block, &strings_block)) {
 212  i :      LOG(ERROR) << "Block graph is missing some COFF special blocks. "
 213    :                 << "Not a COFF block graph?";
 214  i :      return false;
 215    :    }
 216  E :    DCHECK(headers_block != NULL);
 217  E :    DCHECK(symbols_block != NULL);
 218  E :    DCHECK(strings_block != NULL);
 219    :  
 220  E :    DCHECK(headers_block_ == NULL);
 221  E :    DCHECK(symbols_block_ == NULL);
 222  E :    DCHECK(strings_block_ == NULL);
 223    :    base::AutoReset<BlockGraph::Block*> auto_reset_headers_block(
 224  E :        &headers_block_, headers_block);
 225    :    base::AutoReset<BlockGraph::Block*> auto_reset_symbols_block(
 226  E :        &symbols_block_, symbols_block);
 227    :    base::AutoReset<BlockGraph::Block*> auto_reset_strings_block(
 228  E :        &strings_block_, strings_block);
 229    :  
 230  E :    if (!LayoutHeaders())
 231  i :      return false;
 232    :  
 233  E :    if (!LayoutSectionBlocks(ordered_graph))
 234  i :      return false;
 235    :  
 236  E :    if (!LayoutSymbolAndStringTables(ordered_graph))
 237  i :      return false;
 238    :  
 239  E :    if (!RemoveOldRelocBlocks())
 240  i :      return false;
 241    :  
 242  E :    return true;
 243  E :  }
 244    :  
 245  E :  bool CoffImageLayoutBuilder::LayoutHeaders() {
 246  E :    DCHECK(headers_block_ != NULL);
 247  E :    DCHECK_EQ(0u, image_layout_->blocks.address_space_impl().size());
 248  E :    DCHECK_EQ(0u, image_layout_->sections.size());
 249    :  
 250  E :    if (IsValidDosHeaderBlock(headers_block_)) {
 251  i :      LOG(ERROR) << "Found DOS header in purported COFF file.";
 252  i :      return false;
 253    :    }
 254    :  
 255    :    // Lay out headers as the block in the image layout.
 256  E :    DCHECK_EQ(0u, cursor_.value());
 257  E :    if (!LayoutBlockImpl(headers_block_))
 258  i :      return false;
 259    :  
 260  E :    return true;
 261  E :  }
 262    :  
 263    :  bool CoffImageLayoutBuilder::LayoutSectionBlocks(
 264  E :      const OrderedBlockGraph& ordered_graph) {
 265  E :    DCHECK(headers_block_ != NULL);
 266  E :    DCHECK(symbols_block_ != NULL);
 267  E :    DCHECK_LT(0u, cursor_.value());
 268  E :    DCHECK_EQ(0u, image_layout_->sections.size());
 269    :  
 270    :    // Fetch pointers to headers.
 271  E :    ConstTypedBlock<IMAGE_FILE_HEADER> file_header;
 272  E :    if (!file_header.Init(0, headers_block_)) {
 273  i :      LOG(ERROR) << "Unable to cast file header.";
 274  i :      return false;
 275    :    }
 276  E :    TypedBlock<IMAGE_SECTION_HEADER> section_headers;
 277  E :    if (!section_headers.Init(sizeof(IMAGE_FILE_HEADER), headers_block_)) {
 278  i :      LOG(ERROR) << "Unable to cast section headers.";
 279  i :      return false;
 280    :    }
 281  E :    if (file_header->NumberOfSections != section_headers.ElementCount()) {
 282  i :      LOG(ERROR) << "File header section count does not agree with "
 283    :                 << "element count in headers block ("
 284    :                 << file_header->NumberOfSections
 285    :                 << " vs " << section_headers.ElementCount() << ").";
 286  i :      return false;
 287    :    }
 288    :  
 289    :    // Fetch pointer to symbols.
 290  E :    ConstTypedBlock<IMAGE_SYMBOL> symbols;
 291  E :    if (!symbols.Init(0, symbols_block_)) {
 292  i :      LOG(ERROR) << "Unable to cast symbol table.";
 293  i :      return false;
 294    :    }
 295  E :    size_t num_symbols = symbols.ElementCount();
 296    :  
 297    :    // Collect symbol information for relocations.
 298  E :    SymbolMap symbol_map;
 299    :    BlockGraph::Block::ReferenceMap::const_iterator it =
 300  E :        symbols_block_->references().begin();
 301  E :    for (size_t i = 0; i < num_symbols; i += 1 + symbols[i].NumberOfAuxSymbols) {
 302  E :      if (it != symbols_block_->references().end()) {
 303  E :        size_t ref_symbol_index = it->first / sizeof(IMAGE_SYMBOL);
 304  E :        DCHECK_LE(i, ref_symbol_index);
 305  E :        DCHECK_GT(num_symbols, ref_symbol_index);
 306    :  
 307  E :        if (i == ref_symbol_index) {
 308    :          // Resolved (referenced) symbol. We override previously inserted
 309    :          // symbols for the same reference; this gives priority to actual
 310    :          // symbols at offset zero, rather than section definition symbols.
 311  E :          DCHECK_LT(0, symbols[i].SectionNumber);
 312    :          std::pair<BlockGraph::Block*, BlockGraph::Offset> ref_pair =
 313  E :            std::make_pair(it->second.referenced(), it->second.base());
 314  E :          symbol_map.insert(std::make_pair(ref_pair, i)).first->second = i;
 315    :  
 316    :          // Skip any other references for this symbol or its auxiliary
 317    :          // symbols.
 318  E :          size_t next_index = i + 1 + symbols[i].NumberOfAuxSymbols;
 319    :          do {
 320  E :            ++it;
 321    :          } while (it != symbols_block_->references().end() &&
 322  E :                   it->first / sizeof(IMAGE_SYMBOL) < next_index);
 323    :  
 324  E :          continue;
 325    :        }
 326    :      }
 327    :  
 328    :      // External or misc (unreferenced), that lies between references.
 329  E :      DCHECK_GE(0, symbols[i].SectionNumber);
 330    :      std::pair<BlockGraph::Block*, BlockGraph::Offset> ref_pair =
 331  E :          std::make_pair(symbols_block_, i * sizeof(symbols[i]));
 332  E :      symbol_map.insert(std::make_pair(ref_pair, i));
 333  E :    }
 334  E :    DCHECK(it == symbols_block_->references().end());
 335    :  
 336    :    // Lay out section and relocation blocks.
 337    :    OrderedBlockGraph::SectionList::const_iterator section_it =
 338  E :        ordered_graph.ordered_sections().begin();
 339    :    OrderedBlockGraph::SectionList::const_iterator section_end =
 340  E :        ordered_graph.ordered_sections().end();
 341  E :    size_t section_index = 0;
 342  E :    for (; section_it != section_end; ++section_it) {
 343  E :      BlockGraph::Section* section = (*section_it)->section();
 344  E :      DCHECK(section != NULL);
 345    :  
 346    :      // Fill in common section header information.
 347  E :      if (section_index >= file_header->NumberOfSections) {
 348  i :        LOG(ERROR) << "Not enough space in headers block for "
 349    :                   << "so many sections (" << section_index << ").";
 350  i :        return false;
 351    :      }
 352  E :      IMAGE_SECTION_HEADER* header = &section_headers[section_index];
 353    :  
 354  E :      std::memset(header, 0, sizeof(*header));
 355    :      std::strncpy(reinterpret_cast<char*>(header->Name),
 356    :                   section->name().c_str(),
 357  E :                   arraysize(header->Name));
 358  E :      header->Characteristics = section->characteristics();
 359    :  
 360    :      // Handle section data.
 361  E :      if (!OpenSection(*section))
 362  i :        return false;
 363    :  
 364  E :      FileOffsetAddress section_start(cursor_.value());
 365  E :      RelocVector relocs;
 366    :  
 367    :      // Lay out section blocks and collect relocations.
 368    :      OrderedBlockGraph::BlockList::const_iterator block_it =
 369  E :          (*section_it)->ordered_blocks().begin();
 370    :      OrderedBlockGraph::BlockList::const_iterator block_end =
 371  E :          (*section_it)->ordered_blocks().end();
 372  E :      for (; block_it != block_end; ++block_it) {
 373  E :        BlockGraph::Block* block = *block_it;
 374  E :        DCHECK(block != NULL);
 375    :        DCHECK(block->type() == BlockGraph::CODE_BLOCK ||
 376    :               (block->attributes() &
 377  E :                (BlockGraph::SECTION_CONTRIB | BlockGraph::COFF_BSS)) != 0);
 378    :  
 379    :        // Fix references.
 380    :        BlockGraph::Block::ReferenceMap::const_iterator ref_it =
 381  E :            block->references().begin();
 382  E :        for (; ref_it != block->references().end(); ++ref_it) {
 383    :          // Section blocks should only have relocations and function-relative
 384    :          // file pointers, represented as section offsets, thanks to
 385    :          // function-level linking.
 386  E :          BlockGraph::Reference ref(ref_it->second);
 387    :          if ((ref.type() & BlockGraph::RELOC_REF_BIT) == 0 &&
 388  E :              ref.type() != BlockGraph::SECTION_OFFSET_REF) {
 389  i :              LOG(ERROR) << "Unexpected reference type " << ref.type()
 390    :                         << " in section " << section_index << ".";
 391  i :              return false;
 392    :          }
 393    :  
 394  E :          switch (ref.size()) {
 395    :            case sizeof(uint32):
 396  E :              if (!WriteReferenceValue<uint32>(ref, ref_it->first, block))
 397  i :                return false;
 398  E :              break;
 399    :            case sizeof(uint16):
 400  E :              if (!WriteReferenceValue<uint16>(ref, ref_it->first, block))
 401  i :                return false;
 402  E :              break;
 403    :            case sizeof(uint8):
 404    :              // TODO(chrisha): This is really a special 7-bit relocation; we do
 405    :              // not touch these, for now.
 406  i :              break;
 407    :            default:
 408  i :              LOG(ERROR) << "Unsupported relocation value size ("
 409    :                         << ref.size() << ").";
 410  i :              return false;
 411    :          }
 412  E :        }
 413    :  
 414    :        // Lay out and collect relocations.
 415  E :        if (!LayoutBlock(block))
 416  i :          return false;
 417  E :        if (!AddRelocs(*block, symbol_map, &relocs))
 418  i :          return false;
 419  E :      }
 420    :  
 421  E :      if (!CloseSection())
 422  i :        return false;
 423    :  
 424    :      // Fix section header. We use section_index - 1, as the value has been
 425    :      // incremented already.
 426    :      const ImageLayout::SectionInfo& info =
 427  E :          image_layout_->sections[section_index];
 428  E :      if ((section->characteristics() & IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0) {
 429    :        // Normal section.
 430  E :        header->PointerToRawData = section_start.value();
 431  E :        header->SizeOfRawData = info.data_size;
 432  E :      } else {
 433    :        // BSS section. The COFF specifications state that SizeOfRawData
 434    :        // should be set to zero, but MSVC sets it to the size of the
 435    :        // uninitialized data.
 436  E :        header->SizeOfRawData = info.size;
 437    :      }
 438  E :      DCHECK_EQ(header->Characteristics, info.characteristics);
 439    :  
 440    :      // Lay out relocations, if necessary.
 441  E :      if (relocs.size() != 0) {
 442  E :        size_t relocs_size = relocs.size() * sizeof(relocs[0]);
 443    :        BlockGraph::Block* relocs_block =
 444    :            image_layout_->blocks.graph()->AddBlock(BlockGraph::DATA_BLOCK,
 445    :                                                    relocs_size,
 446  E :                                                    kNewRelocsBlockName);
 447  E :        DCHECK(relocs_block != NULL);
 448  E :        relocs_block->set_attribute(BlockGraph::COFF_RELOC_DATA);
 449  E :        if (relocs_block->CopyData(relocs_size, &relocs[0]) == NULL)
 450  i :          return false;
 451    :  
 452    :        // Fix relocation information in header.
 453  E :        header->PointerToRelocations = cursor_.value();
 454  E :        header->NumberOfRelocations = relocs.size();
 455    :  
 456    :        // Lay out the relocation block outside of the section.
 457  E :        if (!LayoutBlockImpl(relocs_block))
 458  i :          return false;
 459    :      }
 460    :  
 461  E :      ++section_index;
 462  E :    }
 463    :  
 464  E :    if (section_index < file_header->NumberOfSections) {
 465  i :      LOG(ERROR) << "Missing sections from ordered block graph ("
 466    :                 << file_header->NumberOfSections << " expected vs "
 467    :                 << section_index << " found).";
 468  i :      return false;
 469    :    }
 470    :  
 471  E :    return true;
 472  E :  }
 473    :  
 474    :  bool CoffImageLayoutBuilder::LayoutSymbolAndStringTables(
 475  E :      const OrderedBlockGraph& ordered_graph) {
 476  E :    DCHECK(headers_block_ != NULL);
 477  E :    DCHECK(symbols_block_ != NULL);
 478  E :    DCHECK(strings_block_ != NULL);
 479    :  
 480  E :    TypedBlock<IMAGE_FILE_HEADER> file_header;
 481  E :    if (!file_header.Init(0, headers_block_)) {
 482  i :      LOG(ERROR) << "Unable to cast file header.";
 483  i :      return false;
 484    :    }
 485    :  
 486  E :    TypedBlock<IMAGE_SYMBOL> symbols;
 487  E :    if (!symbols.Init(0, symbols_block_)) {
 488  i :      LOG(ERROR) << "Unable to cast symbol table.";
 489  i :      return false;
 490    :    }
 491    :  
 492  E :    file_header->PointerToSymbolTable = cursor_.value();
 493  E :    file_header->NumberOfSymbols = symbols.ElementCount();
 494    :  
 495    :    // Lay out the blocks.
 496  E :    if (!LayoutBlockImpl(symbols_block_))
 497  i :      return false;
 498  E :    if (!LayoutBlockImpl(strings_block_))
 499  i :      return false;
 500    :  
 501    :    // Compute the section index map, used to remap symbol section references.
 502  E :    SectionIndexMap section_index_map;
 503    :    OrderedBlockGraph::SectionList::const_iterator section_it =
 504  E :        ordered_graph.ordered_sections().begin();
 505    :    OrderedBlockGraph::SectionList::const_iterator section_end =
 506  E :        ordered_graph.ordered_sections().end();
 507  E :    size_t section_index = 0;
 508  E :    for (; section_it != section_end; ++section_it) {
 509  E :      BlockGraph::Section* section = (*section_it)->section();
 510  E :      DCHECK(section != NULL);
 511  E :      section_index_map.insert(std::make_pair(section->id(), section_index));
 512  E :      ++section_index;
 513  E :    }
 514    :  
 515    :    // Fix references.
 516    :    BlockGraph::Block::ReferenceMap::const_iterator it =
 517  E :        symbols_block_->references().begin();
 518  E :    for (; it != symbols_block_->references().end(); ++it) {
 519  E :      size_t symbol_index = it->first / sizeof(IMAGE_SYMBOL);
 520  E :      DCHECK_GT(file_header->NumberOfSymbols, symbol_index);
 521    :  
 522  E :      switch (it->second.type()) {
 523    :        case BlockGraph::SECTION_REF: {
 524  E :          DCHECK_EQ(2u, it->second.size());
 525  E :          TypedBlock<uint16> section_number;
 526  E :          if (!section_number.Init(it->first, symbols_block_)) {
 527  i :            LOG(ERROR) << "Unable to cast reference.";
 528  i :            return false;
 529    :          }
 530    :  
 531    :          SectionIndexMap::iterator section_index_it =
 532  E :              section_index_map.find(it->second.referenced()->section());
 533  E :          if (section_index_it == section_index_map.end()) {
 534  i :            LOG(ERROR) << "Reference to unmapped section.";
 535  i :            return false;
 536    :          }
 537  E :          *section_number = section_index_it->second + 1;
 538  E :          DCHECK_EQ(*section_number, symbols[symbol_index].SectionNumber);
 539  E :          break;
 540    :        }
 541    :  
 542    :        case BlockGraph::SECTION_OFFSET_REF: {
 543  E :          DCHECK_EQ(4u, it->second.size());
 544  E :          TypedBlock<uint32> value;
 545  E :          if (!value.Init(it->first, symbols_block_)) {
 546  i :            LOG(ERROR) << "Unable to cast reference.";
 547  i :            return false;
 548    :          }
 549    :  
 550  E :          *value = it->second.offset();
 551    :          DCHECK_EQ(static_cast<size_t>(it->second.offset()),
 552  E :                    symbols[symbol_index].Value);
 553  E :          break;
 554    :        }
 555    :  
 556    :        default:
 557  i :          LOG(ERROR) << "Unexpected reference type " << it->second.type()
 558    :                     << " in symbol table.";
 559  i :          return false;
 560    :      }
 561  E :    }
 562    :  
 563  E :    return true;
 564  E :  }
 565    :  
 566  E :  bool CoffImageLayoutBuilder::RemoveOldRelocBlocks() {
 567    :    // Find blocks not mapped in the image layout, and ensure they are (old)
 568    :    // COFF relocation blocks; if not, that is an error.
 569    :    //
 570    :    // Relocation blocks found during this pass do not include new relocation
 571    :    // blocks (which must have been inserted into the image layout).
 572    :    BlockGraph::BlockMap& blocks =
 573  E :        image_layout_->blocks.graph()->blocks_mutable();
 574  E :    std::vector<BlockGraph::Block*> blocks_to_remove;
 575    :  
 576  E :    BlockGraph::BlockMap::iterator it = blocks.begin();
 577  E :    for (; it != blocks.end(); ++it) {
 578  E :      if (!image_layout_->blocks.ContainsBlock(&it->second)) {
 579  E :        if ((it->second.attributes() & BlockGraph::COFF_RELOC_DATA) == 0) {
 580  i :          LOG(ERROR) << "Found unmapped block \"" << it->second.name()
 581    :                     << "\" in block graph; "
 582    :                     << "originally mapped at address " << it->second.addr()
 583    :                     << ".";
 584  i :          return false;
 585    :        }
 586  E :        blocks_to_remove.push_back(&it->second);
 587    :      }
 588  E :    }
 589    :  
 590    :    // Remove old relocation blocks from the block graph.
 591    :    std::vector<BlockGraph::Block*>::iterator it_to_remove =
 592  E :        blocks_to_remove.begin();
 593  E :    for (; it_to_remove != blocks_to_remove.end(); ++it_to_remove) {
 594  E :      if (!image_layout_->blocks.graph()->RemoveBlock(*it_to_remove)) {
 595  i :        LOG(ERROR) << "Unable to remove block with ID " << (*it_to_remove)->id()
 596    :                   << " from the block graph.";
 597    :      }
 598  E :    }
 599    :  
 600    :    DCHECK_EQ(image_layout_->blocks.size(),
 601  E :              image_layout_->blocks.graph()->blocks().size());
 602    :  
 603  E :    return true;
 604  E :  }
 605    :  
 606    :  }  // namespace pe

Coverage information generated Thu Jan 14 17:40:38 2016.