Coverage for /Syzygy/pe/transforms/coff_rename_symbols_transform.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
96.4%80830.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    :  #include "syzygy/pe/transforms/coff_rename_symbols_transform.h"
  16    :  
  17    :  #include <string>
  18    :  #include <vector>
  19    :  
  20    :  #include "base/bind.h"
  21    :  #include "syzygy/block_graph/typed_block.h"
  22    :  #include "syzygy/pe/coff_utils.h"
  23    :  
  24    :  namespace pe {
  25    :  namespace transforms {
  26    :  
  27    :  namespace {
  28    :  
  29    :  using block_graph::BlockGraph;
  30    :  using block_graph::TypedBlock;
  31    :  
  32    :  void AddSymbol(const base::StringPiece& symbol_name,
  33    :                 BlockGraph::Offset template_offset,
  34    :                 BlockGraph::Block* symbols_block,
  35    :                 BlockGraph::Block* strings_block,
  36  E :                 BlockGraph::Offset* symbol_offset) {
  37  E :    DCHECK_NE(reinterpret_cast<BlockGraph::Block*>(NULL), symbols_block);
  38  E :    DCHECK_NE(reinterpret_cast<BlockGraph::Block*>(NULL), strings_block);
  39  E :    DCHECK_NE(reinterpret_cast<BlockGraph::Offset*>(NULL), symbol_offset);
  40    :  
  41  E :    TypedBlock<IMAGE_SYMBOL> symbols;
  42  E :    CHECK(symbols.Init(0, symbols_block));
  43  E :    size_t symbol_count = symbols.ElementCount();
  44  E :    *symbol_offset = sizeof(IMAGE_SYMBOL) * symbol_count;
  45  E :    symbols_block->InsertData(*symbol_offset, sizeof(IMAGE_SYMBOL), true);
  46  E :    size_t template_index = template_offset / sizeof(IMAGE_SYMBOL);
  47  E :    IMAGE_SYMBOL* orig = &symbols[template_index];
  48  E :    IMAGE_SYMBOL* symbol = &symbols[symbol_count];
  49    :  
  50    :    // Copy the metadata from the template symbol. We set the section number to
  51    :    // zero to indicate that this is an external symbol that has no definition in
  52    :    // this COFF file. It will be satisfied at link time.
  53  E :    symbol->Value = orig->Value;
  54  E :    symbol->SectionNumber = 0;
  55  E :    symbol->Type = orig->Type;
  56  E :    symbol->StorageClass = orig->StorageClass;
  57  E :    symbol->NumberOfAuxSymbols = 0;
  58    :  
  59    :    // Determine whether the name goes in the string table or is embedded in the
  60    :    // symbol record itself.
  61  E :    char* symbol_name_dst = NULL;
  62  E :    if (symbol_name.size() <= sizeof(symbol->N.ShortName)) {
  63  E :      symbol_name_dst = reinterpret_cast<char*>(symbol->N.ShortName);
  64  E :    } else {
  65  E :      size_t string_offset = strings_block->size();
  66  E :      strings_block->set_size(strings_block->size() + symbol_name.size() + 1);
  67  E :      strings_block->ResizeData(strings_block->size());
  68    :      symbol_name_dst = reinterpret_cast<char*>(
  69  E :          strings_block->GetMutableData()) + string_offset;
  70  E :      symbol->N.Name.Long = string_offset;
  71    :    }
  72    :  
  73    :    // Copy the symbol name. We don't explicitly copy the terminating NULL, as
  74    :    // the data structure was initialized with zeros and we don't always need one
  75    :    // (the case of an 8-byte name, which is stored directly in the symbol).
  76  E :    ::memcpy(symbol_name_dst, symbol_name.data(), symbol_name.size());
  77    :  
  78    :    return;
  79  E :  }
  80    :  
  81    :  void TransferReferrers(BlockGraph::Offset src_offset,
  82    :                         BlockGraph::Offset dst_offset,
  83  E :                         BlockGraph::Block* block) {
  84  E :    DCHECK_NE(reinterpret_cast<BlockGraph::Block*>(NULL), block);
  85    :  
  86    :    // Make a copy of the referrers set because we'll be modifying the original
  87    :    // as we traverse.
  88  E :    BlockGraph::Block::ReferrerSet referrers = block->referrers();
  89  E :    BlockGraph::Block::ReferrerSet::const_iterator ref_it = referrers.begin();
  90  E :    for (; ref_it != referrers.end(); ++ref_it) {
  91  E :      BlockGraph::Reference ref;
  92  E :      CHECK(ref_it->first->GetReference(ref_it->second, &ref));
  93  E :      DCHECK_EQ(block, ref.referenced());
  94  E :      if (ref.offset() != src_offset)
  95  E :        continue;
  96    :  
  97  E :      BlockGraph::Offset delta = ref.base() - ref.offset();
  98    :      ref = BlockGraph::Reference(ref.type(), ref.size(), ref.referenced(),
  99  E :                                  dst_offset, dst_offset + delta);
 100  E :      CHECK(!ref_it->first->SetReference(ref_it->second, ref));
 101  E :    }
 102  E :  }
 103    :  
 104    :  }  // namespace
 105    :  
 106    :  const char CoffRenameSymbolsTransform::kTransformName[] =
 107    :      "CoffRenameSymbolsTransform";
 108    :  
 109    :  void CoffRenameSymbolsTransform::AddSymbolMapping(const base::StringPiece& from,
 110  E :                                                    const base::StringPiece& to) {
 111  E :    mappings_.push_back(std::make_pair(from.as_string(), to.as_string()));
 112  E :  }
 113    :  
 114    :  bool CoffRenameSymbolsTransform::TransformBlockGraph(
 115    :      const TransformPolicyInterface* policy,
 116    :      BlockGraph* block_graph,
 117  E :      BlockGraph::Block* /* headers_block */) {
 118  E :    DCHECK_NE(reinterpret_cast<TransformPolicyInterface*>(NULL), policy);
 119  E :    DCHECK_NE(reinterpret_cast<BlockGraph*>(NULL), block_graph);
 120  E :    DCHECK_EQ(BlockGraph::COFF_IMAGE, block_graph->image_format());
 121    :  
 122    :    BlockGraph::Block* symbols_block;
 123    :    BlockGraph::Block* strings_block;
 124    :    if (!FindCoffSpecialBlocks(block_graph,
 125  E :                               NULL, &symbols_block, &strings_block)) {
 126  i :      LOG(ERROR) << "Block graph is missing some COFF special blocks. "
 127    :                 << "Not a COFF block graph?";
 128  i :      return false;
 129    :    }
 130    :  
 131  E :    CoffSymbolNameOffsetMap symbol_offset_map;
 132    :    if (!BuildCoffSymbolNameOffsetMap(symbols_block, strings_block,
 133  E :                                      &symbol_offset_map)) {
 134  i :      return false;
 135    :    }
 136    :  
 137  E :    for (size_t i = 0; i < mappings_.size(); ++i) {
 138  E :      const std::string& src = mappings_[i].first;
 139  E :      const std::string& dst = mappings_[i].second;
 140    :      CoffSymbolNameOffsetMap::const_iterator src_it =
 141  E :          symbol_offset_map.find(src);
 142  E :      if (src_it == symbol_offset_map.end()) {
 143  E :        if (symbols_must_exist_) {
 144  E :          LOG(ERROR) << "Unable to find source symbol \"" << src << "\".";
 145  E :          return false;
 146    :        }
 147    :  
 148    :        // Input symbols aren't forced to exist, so continue on to the next one.
 149  E :        continue;
 150    :      }
 151  E :      DCHECK(!src_it->second.empty());
 152    :  
 153    :      // Find the destination offset.
 154    :      CoffSymbolNameOffsetMap::const_iterator dst_it =
 155  E :          symbol_offset_map.find(dst);
 156  E :      BlockGraph::Offset dst_offset = 0;
 157  E :      if (dst_it != symbol_offset_map.end()) {
 158    :        // If the destination is multiply defined we simply take the first one.
 159  E :        DCHECK(!dst_it->second.empty());
 160  E :        dst_offset = *dst_it->second.begin();
 161  E :      } else {
 162    :        // If the symbol does not exist, then append it to the strings block.
 163    :        // Use the first symbol as canonical for the purpose of symbol metadata.
 164  E :        BlockGraph::Offset src_offset = *src_it->second.begin();
 165    :        AddSymbol(dst, src_offset, symbols_block, strings_block,
 166  E :                  &dst_offset);
 167    :      }
 168    :  
 169    :      // Iterate over all source symbols with this name and transfer references
 170    :      // from them to the destination symbol.
 171  E :      const CoffSymbolOffsets& src_offsets = src_it->second;
 172  E :      CoffSymbolOffsets::const_iterator src_offset_it = src_offsets.begin();
 173  E :      for (; src_offset_it != src_offsets.end(); ++src_offset_it) {
 174  E :        BlockGraph::Offset src_offset = *src_offset_it;
 175  E :        TransferReferrers(src_offset, dst_offset, symbols_block);
 176  E :      }
 177  E :    }
 178    :  
 179  E :    return true;
 180  E :  }
 181    :  
 182    :  }  // namespace transforms
 183    :  }  // namespace pe

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