Coverage for /Syzygy/instrument/transforms/jump_table_count_transform_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%70700.C++test

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    :  // Jump table case count instrumentation transform unit-tests.
  16    :  
  17    :  #include "syzygy/instrument/transforms/jump_table_count_transform.h"
  18    :  
  19    :  #include "gtest/gtest.h"
  20    :  #include "syzygy/block_graph/basic_block.h"
  21    :  #include "syzygy/block_graph/basic_block_decomposer.h"
  22    :  #include "syzygy/block_graph/basic_block_subgraph.h"
  23    :  #include "syzygy/block_graph/block_graph.h"
  24    :  #include "syzygy/block_graph/block_util.h"
  25    :  #include "syzygy/block_graph/typed_block.h"
  26    :  #include "syzygy/common/indexed_frequency_data.h"
  27    :  #include "syzygy/instrument/transforms/unittest_util.h"
  28    :  
  29    :  #include "mnemonics.h"  // NOLINT
  30    :  
  31    :  namespace instrument {
  32    :  namespace transforms {
  33    :  
  34    :  namespace {
  35    :  
  36    :  using block_graph::BasicBlock;
  37    :  using block_graph::BasicCodeBlock;
  38    :  using block_graph::BasicBlockDecomposer;
  39    :  using block_graph::BasicBlockSubGraph;
  40    :  using block_graph::BlockGraph;
  41    :  using block_graph::Instruction;
  42    :  using common::IndexedFrequencyData;
  43    :  
  44    :  class TestJumpTableCaseCountTransform : public JumpTableCaseCountTransform {
  45    :   public:
  46    :    using JumpTableCaseCountTransform::add_frequency_data;
  47    :    using JumpTableCaseCountTransform::jump_table_case_counter_hook_ref;
  48    :    using JumpTableCaseCountTransform::thunk_section;
  49    :  
  50  E :    BlockGraph::Block* frequency_data_block() {
  51  E :      return add_frequency_data()->frequency_data_block();
  52  E :    }
  53    :  
  54  E :    BlockGraph::Block* frequency_data_buffer_block() {
  55  E :      return add_frequency_data()->frequency_data_buffer_block();
  56  E :    }
  57    :  };
  58    :  
  59    :  typedef testing::TestDllTransformTest JumpTableCaseCountTransformTest;
  60    :  
  61    :  // Ensures that the @p block is a jump table case count thunk.
  62  E :  void CheckBlockIsAThunk(BlockGraph::Block* block) {
  63    :    // Decompose the block to basic-blocks.
  64  E :    BasicBlockSubGraph subgraph;
  65  E :    BasicBlockDecomposer bb_decomposer(block, &subgraph);
  66  E :    ASSERT_TRUE(bb_decomposer.Decompose());
  67    :  
  68  E :    ASSERT_EQ(2u, subgraph.basic_blocks().size());
  69    :    const BasicCodeBlock* bb = BasicCodeBlock::Cast(
  70  E :        *subgraph.basic_blocks().begin());
  71  E :    ASSERT_TRUE(bb != NULL);
  72  E :    ASSERT_FALSE(bb->is_padding());
  73    :  
  74  E :    ASSERT_EQ(2U, bb->instructions().size());
  75    :    BasicBlock::Instructions::const_iterator inst_iter =
  76  E :        bb->instructions().begin();
  77    :  
  78    :    // Instruction 1 should push the case id.
  79  E :    EXPECT_EQ(I_PUSH, inst_iter->representation().opcode);
  80    :  
  81    :    // Instruction 2 should call the jump table counter hook.
  82  E :    ++inst_iter;
  83  E :    EXPECT_EQ(I_CALL, inst_iter->representation().opcode);
  84    :  
  85    :    EXPECT_EQ(BasicBlock::BASIC_END_BLOCK,
  86  E :              (*subgraph.basic_blocks().rbegin())->type());
  87  E :  }
  88    :  
  89    :  }  // namespace
  90    :  
  91  E :  TEST_F(JumpTableCaseCountTransformTest, Apply) {
  92  E :    ASSERT_NO_FATAL_FAILURE(DecomposeTestDll());
  93    :  
  94    :    // Apply the transform.
  95  E :    TestJumpTableCaseCountTransform tx;
  96    :    ASSERT_TRUE(block_graph::ApplyBlockGraphTransform(
  97  E :        &tx, policy_, &block_graph_, header_block_));
  98  E :    ASSERT_TRUE(tx.frequency_data_block() != NULL);
  99  E :    ASSERT_TRUE(tx.thunk_section() != NULL);
 100  E :    ASSERT_TRUE(tx.jump_table_case_counter_hook_ref() != NULL);
 101  E :    ASSERT_TRUE(tx.jump_table_case_counter_hook_ref()->IsValid());
 102    :  
 103    :    // Validate the jump table frequency data structure.
 104  E :    block_graph::ConstTypedBlock<IndexedFrequencyData> frequency_data;
 105  E :    ASSERT_TRUE(frequency_data.Init(0, tx.frequency_data_block()));
 106  E :    EXPECT_EQ(sizeof(uint32), frequency_data->frequency_size);
 107  E :    EXPECT_EQ(common::kJumpTableCountAgentId, frequency_data->agent_id);
 108  E :    EXPECT_EQ(common::kJumpTableFrequencyDataVersion, frequency_data->version);
 109  E :    EXPECT_EQ(IndexedFrequencyData::JUMP_TABLE, frequency_data->data_type);
 110  E :    EXPECT_EQ(sizeof(IndexedFrequencyData), tx.frequency_data_block()->size());
 111    :    EXPECT_EQ(sizeof(IndexedFrequencyData),
 112  E :              tx.frequency_data_block()->data_size());
 113    :    EXPECT_TRUE(frequency_data.HasReferenceAt(
 114  E :        frequency_data.OffsetOf(frequency_data->frequency_data)));
 115  E :    BlockGraph::Reference frequency_data_reference;
 116    :    ASSERT_TRUE(frequency_data.block()->GetReference(
 117    :        frequency_data.OffsetOf(frequency_data->frequency_data),
 118  E :        &frequency_data_reference));
 119    :    EXPECT_EQ(frequency_data_reference.referenced(),
 120  E :              tx.frequency_data_buffer_block());
 121    :    EXPECT_EQ(frequency_data->num_entries * frequency_data->frequency_size,
 122  E :              tx.frequency_data_buffer_block()->size());
 123    :  
 124    :    // Examine each eligible block to verify that all the jump tables have
 125    :    // been instrumented.
 126  E :    size_t jump_table_entries = 0;
 127  E :    for (BlockGraph::BlockMap::const_iterator block_iter(
 128    :             block_graph_.blocks().begin());
 129  E :        block_iter != block_graph_.blocks().end();
 130  E :        ++block_iter) {
 131  E :      const BlockGraph::Block& block = block_iter->second;
 132    :  
 133    :      // Skip non-code blocks.
 134  E :      if (block.type() != BlockGraph::CODE_BLOCK)
 135  E :        continue;
 136    :  
 137    :      // We don't want to check the thunk blocks.
 138  E :      if (block.section() == tx.thunk_section()->id())
 139  E :        continue;
 140    :  
 141    :      // Iterate over the labels to find the jump tables.
 142  E :      for (BlockGraph::Block::LabelMap::const_iterator iter_label(
 143    :               block.labels().begin());
 144  E :          iter_label != block.labels().end();
 145  E :          ++iter_label) {
 146  E :        if (!iter_label->second.has_attributes(BlockGraph::JUMP_TABLE_LABEL))
 147  E :          continue;
 148    :  
 149  E :        size_t table_size = 0;
 150    :        ASSERT_TRUE(
 151  E :            block_graph::GetJumpTableSize(&block, iter_label, &table_size));
 152    :  
 153    :        BlockGraph::Block::ReferenceMap::const_iterator iter_ref =
 154  E :            block.references().find(iter_label->first);
 155  E :        ASSERT_TRUE(iter_ref != block.references().end());
 156    :  
 157    :        // Iterate over the references and ensure that they are thunked.
 158  E :        for (size_t i = 0; i < table_size; ++i) {
 159  E :          BlockGraph::Block* ref_block = iter_ref->second.referenced();
 160  E :          CheckBlockIsAThunk(ref_block);
 161  E :          ++iter_ref;
 162  E :        }
 163    :  
 164  E :        jump_table_entries += table_size;
 165  E :      }
 166  E :    }
 167  E :    DCHECK_EQ(frequency_data->num_entries, jump_table_entries);
 168  E :  }
 169    :  
 170    :  }  // namespace transforms
 171    :  }  // namespace instrument

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