1 : // Copyright 2015 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 : // Declaration of the filler instrumentation transform. This instruments a given
16 : // list of functions by injecting NOP fillers at various places.
17 :
18 : #ifndef SYZYGY_INSTRUMENT_TRANSFORMS_FILLER_TRANSFORM_H_
19 : #define SYZYGY_INSTRUMENT_TRANSFORMS_FILLER_TRANSFORM_H_
20 :
21 : #include <map>
22 : #include <set>
23 : #include <string>
24 :
25 : #include "base/macros.h"
26 : #include "base/files/file_path.h"
27 : #include "syzygy/block_graph/basic_block.h"
28 : #include "syzygy/block_graph/block_graph.h"
29 : #include "syzygy/block_graph/transforms/iterative_transform.h"
30 : #include "syzygy/block_graph/transforms/named_transform.h"
31 :
32 : using block_graph::TransformPolicyInterface;
33 :
34 : namespace instrument {
35 : namespace transforms {
36 :
37 : // A class to transform subgraph by injecting NOP fillers to basic code blocks.
38 : class FillerBasicBlockTransform
39 : : public block_graph::transforms::NamedBasicBlockSubGraphTransformImpl<
40 : FillerBasicBlockTransform> {
41 : public:
42 : typedef block_graph::BasicBlock BasicBlock;
43 : typedef block_graph::BasicBlockSubGraph BasicBlockSubGraph;
44 : typedef block_graph::BasicCodeBlock BasicCodeBlock;
45 : typedef block_graph::BlockGraph BlockGraph;
46 : typedef block_graph::TransformPolicyInterface TransformPolicyInterface;
47 : typedef BlockGraph::Block Block;
48 :
49 : // NOP sizes that can be realized with a single instruction. We disallow
50 : // multi-instruction NOPs to ensure consistent instruction indexes after NOP
51 : // injection.
52 : enum NopSizes {
53 : NOP1 = 1,
54 : NOP2,
55 : NOP3,
56 : NOP4,
57 : NOP5,
58 : NOP6,
59 : NOP7,
60 : NOP8,
61 : NOP9,
62 : NOP10,
63 : NOP11,
64 : };
65 :
66 : // A map from instruction indices to NOP sizes. For example,
67 : // {1: NOP3, 3: NOP2, 4: NOP5} specifies a transformation that takes
68 : // instruction sequence "ABCDE" to "AXBYZCDE", where "X" is the 3-byte NOP,
69 : // "Y" is the 2-byte NOP, and "Z" is the 5-byte NOP.
70 : typedef std::map<size_t, NopSizes> NopSpec;
71 :
72 E : FillerBasicBlockTransform()
73 : : debug_friendly_(false) { }
74 E : virtual ~FillerBasicBlockTransform() { }
75 :
76 : // For NamedBlockGraphTransformImpl.
77 : static const char kTransformName[];
78 :
79 : // @name Accessors and mutators.
80 : // @{
81 : bool debug_friendly() const { return debug_friendly_; }
82 E : void set_debug_friendly(bool flag) { debug_friendly_ = flag; }
83 : // @}
84 :
85 : // Injects NOP into @p instruction. @p nop_spec specifies post-injection
86 : // instruction indices and sizes of NOPs. We do not inject beyond the last
87 : // instruction.
88 : static void InjectNop(const NopSpec& nop_spec,
89 : bool debug_friendly,
90 : BasicBlock::Instructions* instructions);
91 :
92 : // @name BasicBlockSubGraphTransformInterface implementation.
93 : // @{
94 : // Applies the filler transform. Specifically, visits every basic code block
95 : // in @p basic_block_subgraph and injects NOP at various places.
96 : bool TransformBasicBlockSubGraph(
97 : const TransformPolicyInterface* policy,
98 : BlockGraph* block_graph,
99 : BasicBlockSubGraph* basic_block_subgraph) override;
100 : // @}
101 :
102 : private:
103 : // Activate the overwriting of source range for created instructions.
104 : bool debug_friendly_;
105 :
106 : DISALLOW_COPY_AND_ASSIGN(FillerBasicBlockTransform);
107 : };
108 :
109 : // A class to apply filler transform, which injects NOPs to basic code blocks
110 : // in a given list of decorated function names.
111 : class FillerTransform
112 : : public block_graph::transforms::IterativeTransformImpl<FillerTransform> {
113 : public:
114 : typedef block_graph::BasicBlockSubGraph BasicBlockSubGraph;
115 : typedef block_graph::BlockGraph BlockGraph;
116 : typedef BlockGraph::Block Block;
117 :
118 : FillerTransform(const std::set<std::string>& target_set, bool add_copy);
119 E : virtual ~FillerTransform() { }
120 :
121 : // Accessors
122 : // @{
123 E : size_t num_targets_updated() const { return num_targets_updated_; }
124 : // @}
125 :
126 : // For NamedBlockGraphTransformImpl.
127 : static const char kTransformName[];
128 :
129 : // @name Accessors and mutators.
130 : // @{
131 E : bool debug_friendly() const { return debug_friendly_; }
132 E : void set_debug_friendly(bool flag) { debug_friendly_ = flag; }
133 E : const std::map<std::string, bool>& target_visited() const {
134 E : return target_visited_;
135 E : }
136 : // @}
137 :
138 : protected:
139 : // Returns whether @p block is a target.
140 : bool ShouldProcessBlock(Block* block) const;
141 :
142 : // Verifies that all targets were found, and displays warning if not.
143 : void CheckAllTargetsFound() const;
144 :
145 : // @name IterativeTransformImpl implementation.
146 : // @{
147 : bool PreBlockGraphIteration(const TransformPolicyInterface* policy,
148 : BlockGraph* block_graph,
149 : Block* header_block);
150 : bool OnBlock(const TransformPolicyInterface* policy,
151 : BlockGraph* block_graph,
152 : Block* block);
153 : bool PostBlockGraphIteration(const TransformPolicyInterface* policy,
154 : BlockGraph* block_graph,
155 : Block* header_block);
156 : // @}
157 :
158 : private:
159 : friend NamedBlockGraphTransformImpl<FillerTransform>;
160 : friend IterativeTransformImpl<FillerTransform>;
161 :
162 : // Activate the overwriting of source range for created instructions.
163 : bool debug_friendly_;
164 :
165 : // Whether to add a dummy copy of each target.
166 : bool add_copy_;
167 :
168 : // Maps from target names to whether a block with given name was visited.
169 : std::map<std::string, bool> target_visited_;
170 :
171 : // Counters used by CheckAllTargetsFound.
172 : // @{
173 : size_t num_blocks_;
174 : size_t num_code_blocks_;
175 : size_t num_targets_updated_;
176 : // @}
177 :
178 : DISALLOW_COPY_AND_ASSIGN(FillerTransform);
179 : };
180 :
181 : } // namespace transforms
182 : } // namespace instrument
183 :
184 : #endif // SYZYGY_INSTRUMENT_TRANSFORMS_FILLER_TRANSFORM_H_
|