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

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
96.4%81840.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 :    size_t copy_size = 0;
  63  E :    if (symbol_name.size() <= sizeof(symbol->N.ShortName)) {
  64  E :      symbol_name_dst = reinterpret_cast<char*>(symbol->N.ShortName);
  65  E :    } else {
  66  E :      size_t string_offset = strings_block->size();
  67  E :      strings_block->set_size(strings_block->size() + symbol_name.size() + 1);
  68  E :      strings_block->ResizeData(strings_block->size());
  69    :      symbol_name_dst = reinterpret_cast<char*>(
  70  E :          strings_block->GetMutableData()) + string_offset;
  71  E :      symbol->N.Name.Long = string_offset;
  72    :    }
  73    :  
  74    :    // Copy the symbol name. We don't explicitly copy the terminating NULL, as
  75    :    // the data structure was initialized with zeros and we don't always need one
  76    :    // (the case of an 8-byte name, which is stored directly in the symbol).
  77  E :    ::memcpy(symbol_name_dst, symbol_name.data(), symbol_name.size());
  78    :  
  79    :    return;
  80  E :  }
  81    :  
  82    :  void TransferReferrers(BlockGraph::Offset src_offset,
  83    :                         BlockGraph::Offset dst_offset,
  84  E :                         BlockGraph::Block* block) {
  85  E :    DCHECK_NE(reinterpret_cast<BlockGraph::Block*>(NULL), block);
  86    :  
  87    :    // Make a copy of the referrers set because we'll be modifying the original
  88    :    // as we traverse.
  89  E :    BlockGraph::Block::ReferrerSet referrers = block->referrers();
  90  E :    BlockGraph::Block::ReferrerSet::const_iterator ref_it = referrers.begin();
  91  E :    for (; ref_it != referrers.end(); ++ref_it) {
  92  E :      BlockGraph::Reference ref;
  93  E :      CHECK(ref_it->first->GetReference(ref_it->second, &ref));
  94  E :      DCHECK_EQ(block, ref.referenced());
  95  E :      if (ref.offset() != src_offset)
  96  E :        continue;
  97    :  
  98  E :      BlockGraph::Offset delta = ref.base() - ref.offset();
  99    :      ref = BlockGraph::Reference(ref.type(), ref.size(), ref.referenced(),
 100  E :                                  dst_offset, dst_offset + delta);
 101  E :      CHECK(!ref_it->first->SetReference(ref_it->second, ref));
 102  E :    }
 103  E :  }
 104    :  
 105    :  }  // namespace
 106    :  
 107    :  const char CoffRenameSymbolsTransform::kTransformName[] =
 108    :      "CoffRenameSymbolsTransform";
 109    :  
 110    :  void CoffRenameSymbolsTransform::AddSymbolMapping(const base::StringPiece& from,
 111  E :                                                    const base::StringPiece& to) {
 112  E :    mappings_.push_back(std::make_pair(from.as_string(), to.as_string()));
 113  E :  }
 114    :  
 115    :  bool CoffRenameSymbolsTransform::TransformBlockGraph(
 116    :      const TransformPolicyInterface* policy,
 117    :      BlockGraph* block_graph,
 118  E :      BlockGraph::Block* /* headers_block */) {
 119  E :    DCHECK_NE(reinterpret_cast<TransformPolicyInterface*>(NULL), policy);
 120  E :    DCHECK_NE(reinterpret_cast<BlockGraph*>(NULL), block_graph);
 121  E :    DCHECK_EQ(BlockGraph::COFF_IMAGE, block_graph->image_format());
 122    :  
 123    :    BlockGraph::Block* symbols_block;
 124    :    BlockGraph::Block* strings_block;
 125    :    if (!FindCoffSpecialBlocks(block_graph,
 126  E :                               NULL, &symbols_block, &strings_block)) {
 127  i :      LOG(ERROR) << "Block graph is missing some COFF special blocks. "
 128    :                 << "Not a COFF block graph?";
 129  i :      return false;
 130    :    }
 131    :  
 132  E :    CoffSymbolNameOffsetMap symbol_offset_map;
 133    :    if (!BuildCoffSymbolNameOffsetMap(symbols_block, strings_block,
 134  E :                                      &symbol_offset_map)) {
 135  i :      return false;
 136    :    }
 137    :  
 138  E :    for (size_t i = 0; i < mappings_.size(); ++i) {
 139  E :      const std::string& src = mappings_[i].first;
 140  E :      const std::string& dst = mappings_[i].second;
 141    :      CoffSymbolNameOffsetMap::const_iterator src_it =
 142  E :          symbol_offset_map.find(src);
 143  E :      if (src_it == symbol_offset_map.end()) {
 144  E :        if (symbols_must_exist_) {
 145  E :          LOG(ERROR) << "Unable to find source symbol \"" << src << "\".";
 146  E :          return false;
 147    :        }
 148    :  
 149    :        // Input symbols aren't forced to exist, so continue on to the next one.
 150  E :        continue;
 151    :      }
 152  E :      DCHECK(!src_it->second.empty());
 153    :  
 154    :      // Find the destination offset.
 155    :      CoffSymbolNameOffsetMap::const_iterator dst_it =
 156  E :          symbol_offset_map.find(dst);
 157  E :      BlockGraph::Offset dst_offset = 0;
 158  E :      if (dst_it != symbol_offset_map.end()) {
 159    :        // If the destination is multiply defined we simply take the first one.
 160  E :        DCHECK(!dst_it->second.empty());
 161  E :        dst_offset = *dst_it->second.begin();
 162  E :      } else {
 163    :        // If the symbol does not exist, then append it to the strings block.
 164    :        // Use the first symbol as canonical for the purpose of symbol metadata.
 165  E :        BlockGraph::Offset src_offset = *src_it->second.begin();
 166    :        AddSymbol(dst, src_offset, symbols_block, strings_block,
 167  E :                  &dst_offset);
 168    :      }
 169    :  
 170    :      // Iterate over all source symbols with this name and transfer references
 171    :      // from them to the destination symbol.
 172  E :      const CoffSymbolOffsets& src_offsets = src_it->second;
 173  E :      CoffSymbolOffsets::const_iterator src_offset_it = src_offsets.begin();
 174  E :      for (; src_offset_it != src_offsets.end(); ++src_offset_it) {
 175  E :        BlockGraph::Offset src_offset = *src_offset_it;
 176  E :        TransferReferrers(src_offset, dst_offset, symbols_block);
 177  E :      }
 178  E :    }
 179    :  
 180  E :    return true;
 181  E :  }
 182    :  
 183    :  }  // namespace transforms
 184    :  }  // namespace pe

Coverage information generated Thu Mar 26 16:15:41 2015.