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

Coverage information generated Wed Dec 11 11:34:16 2013.