blob: 98773ec10caa67f84745a797b1086c6cd3b71171 [file] [log] [blame]
// Copyright 2013 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Implementation of the jump table count instrumentation transform.
//
// The purpose of this instrumentation is to count the number of times each jump
// table entry is dereferenced. To do this we redirect each reference in the
// jump tables to the following hook:
// push unique_id_for_this_case
// call jump_table_count.dll!_jump_table_case_counter
// jmp original_reference
#ifndef SYZYGY_INSTRUMENT_TRANSFORMS_JUMP_TABLE_COUNT_TRANSFORM_H_
#define SYZYGY_INSTRUMENT_TRANSFORMS_JUMP_TABLE_COUNT_TRANSFORM_H_
#include <string>
#include <utility>
#include <vector>
#include "syzygy/block_graph/basic_block.h"
#include "syzygy/block_graph/transforms/iterative_transform.h"
#include "syzygy/block_graph/transforms/named_transform.h"
#include "syzygy/instrument/transforms/add_indexed_frequency_data_transform.h"
namespace instrument {
namespace transforms {
// An iterative transform that instruments the accesses to the jump/case tables
// to measure the frequency of each case.
class JumpTableCaseCountTransform
: public block_graph::transforms::IterativeTransformImpl<
JumpTableCaseCountTransform> {
public:
// Initialize a new JumpTableCaseCountTransform instance using the default
// module and function names.
JumpTableCaseCountTransform();
protected:
typedef block_graph::BlockGraph BlockGraph;
typedef block_graph::TransformPolicyInterface TransformPolicyInterface;
// @name Accessors. For testing.
// @{
const BlockGraph::Section* thunk_section() const { return thunk_section_; }
AddIndexedFrequencyDataTransform* add_frequency_data() {
return &add_frequency_data_;
}
BlockGraph::Reference* jump_table_case_counter_hook_ref() {
return &jump_table_case_counter_hook_ref_;
}
// @}
private:
friend NamedBlockGraphTransformImpl<JumpTableCaseCountTransform>;
friend IterativeTransformImpl<JumpTableCaseCountTransform>;
typedef core::RelativeAddress RelativeAddress;
// A pair containing the address of a jump-table and its size.
typedef std::pair<RelativeAddress, size_t> JumpTableInfo;
typedef std::vector<JumpTableInfo> JumpTableVector;
// The name of this transform.
static const char kTransformName[];
// @name IterativeTransformImpl implementation.
// @{
bool PreBlockGraphIteration(const TransformPolicyInterface* policy,
BlockGraph* block_graph,
BlockGraph::Block* header_block);
bool OnBlock(const TransformPolicyInterface* policy,
BlockGraph* block_graph,
BlockGraph::Block* block);
bool PostBlockGraphIteration(const TransformPolicyInterface* policy,
BlockGraph* block_graph,
BlockGraph::Block* header_block);
// @}
// Creates a single thunk to destination.
// @param block_graph the block-graph being instrumented.
// @param destination the destination reference.
// @returns a pointer to the thunk on success, NULL otherwise.
BlockGraph::Block* CreateOneThunk(BlockGraph* block_graph,
const BlockGraph::Reference& destination);
// The section we put our thunks in.
BlockGraph::Section* thunk_section_;
// Adds the jump table frequency data referenced by the jump-table
// instrumentation.
AddIndexedFrequencyDataTransform add_frequency_data_;
// The entry hook to which jump table entry events are directed.
BlockGraph::Reference jump_table_case_counter_hook_ref_;
// The instrumentation dll used by this transform.
std::string instrument_dll_name_;
// The counter used to get a unique ID for each case in a jump table.
size_t jump_table_case_count_;
// The different jump tables encountered; we store their addresses and sizes.
JumpTableVector jump_table_infos_;
DISALLOW_COPY_AND_ASSIGN(JumpTableCaseCountTransform);
};
} // namespace transforms
} // namespace instrument
#endif // SYZYGY_INSTRUMENT_TRANSFORMS_JUMP_TABLE_COUNT_TRANSFORM_H_